1. 整体思路:为什么选了 VS Code 来写 LaTeX
先交代一下背景。我之前写过挺长时间 LaTeX 文档,用的是 TeXstudio,后来折腾过一阵 Sublime Text + SumatraPDF 的组合,最后在 VS Code 里彻底扎下来了。这篇文章想聊的,不是“怎么装一个能用就行”的环境,而是我在 VS Code 里配置 LaTeX 编译环境时沉淀下来的那套完整方案,包括为什么这么配、每个配置项到底在干什么、遇到报错怎么排查。
先说结论:VS Code 目前是写 LaTeX 体验最均衡的编辑器。原因很朴素,它把“编辑体验”和“编译链路”彻底拆开了。你在 VS Code 里写 .tex 文件,它管语法高亮、补全、格式化、目录大纲、快捷键;真正把 .tex 变成 PDF 的是背后那套 TeX 发行版和编译工具链。这两层各司其职,谁也不绑架谁,出了问题也好定位——是编辑器的问题还是工具链的问题,一目了然。
这个拆分的思路特别像做饭:VS Code 是厨房台面,负责备菜、摆盘、调味,而 TeX Live / MiKTeX 是灶台和锅,负责真正把菜烧熟。很多初学者会遇到一个困惑:我装了 VS Code 是不是就能编译 LaTeX 了?答案是不行,VS Code 本身不包含 TeX 编译器,它只是把编译命令交给了 LaTeX Workshop 这个插件,由插件去调用你系统里已经装好的 xelatex、pdflatex 或者 latexmk 这些可执行文件。
所以整个配置工作的核心逻辑只有三条:
- 装一个完整的 TeX 发行版,让系统里有 xelatex、pdflatex、latexmk 等编译命令。
- 在 VS Code 里装 LaTeX Workshop 插件,让它能找到这些命令。
- 按需微调 LaTeX Workshop 的配置项,解决中文支持、PDF 预览、正反向同步这一类实际使用中的细节问题。
整套流程理顺之后,以后换一台新电脑,最多二十分钟就能复现同样一套写作环境。下面我按这条线逐步展开。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 环境准备:从零搭好三样东西
2.1 选 TeX 发行版:TeX Live 还是 MiKTeX
第一步是安装 TeX 发行版。这是整套环境的底座,决定你系统里有哪些编译命令、宏包是否完整、跨平台兼容性如何。
我自己用的是 TeX Live,主要看重三点:跨平台统一、默认包含的宏包非常全、更新节奏稳定。TeX Live 在 Windows、macOS、Linux 上都有对应的发行方式,如果你以后需要在不同系统之间切换,用同一套 TeX Live 能省掉很多“这个命令怎么没了”的麻烦。
MiKTeX 的优势是轻量、按需自动安装宏包,装完占用空间小,适合硬盘紧张或者只需要偶尔编译简单文档的场景。不过它默认的“自动安装缺失宏包”这个机制在离线或者网络差的环境下会拖慢编译速度。初学者我一般建议直接 TeX Live,别在选型上花太多心思。
2.2 安装 TeX Live 时的实际步骤
在 Windows 上,去清华镜像站或者中科大镜像站下载 TeX Live 的 ISO 镜像,或者直接下载 install-tl-windows.exe 这个安装引导程序。不要从官网直接拉,官网经常被墙或者速度极慢,镜像站又快又稳。
下载之后双击 install-tl-windows.exe,安装界面里有几个设置项值得注意:
- 安装路径:默认在 C 盘,建议改到 D 盘这类非系统盘,比如 D:\texlive,因为完整安装会占用大概 6 到 8 GB 空间。
- 安装方案:默认是 full scheme,装全部宏包。如果你只写普通论文,可以选 scheme-small,但我不推荐,因为 LaTeX 的宏包依赖经常超出你预期,缺一个再去补很痛苦。
- 安装时间:完整安装可能要花半小时以上,取决于硬盘速度和网络。中间不要强制中断,中断容易让安装器无法修复。
macOS 上可以直接下载 MacTeX,本质上是 TeX Live 的 macOS 发行版,多带了一些 GUI 工具(比如 TeX Live Utility)。Homebrew 用户也可以用 brew install --cask mactex,但要注意安装体积非常大。
Linux 用户直接用发行版的包管理器即可,比如 Ubuntu 上 sudo apt install texlive-full,但注意 apt 源的 TeX Live 版本通常比官方最新版旧一些,宏包老旧有时候会引发兼容性警告,这个要有点心理准备。
2.3 验证 TeX 发行版是否安装成功
装完之后,打开终端(Windows 是 PowerShell 或 CMD,macOS/Linux 是 Terminal),敲一行命令确认环境已经就绪:
bash复制xelatex --version
如果能看到版本号输出,说明编译命令已经加入系统的 PATH 环境变量了,这一步很关键。如果提示“不是内部或外部命令”或者“command not found”,说明安装时没有把 bin 目录加入 PATH,需要手动配置环境变量,这个在后面的常见问题章节里会展开细说。
这里补充一个我个人强烈建议的做法:检验环境是否好用,不要直接打开 VS Code,先在终端里手动编译一个最简文档。新建一个 test.tex 文件,内容就三行:
latex复制\documentclass{article}
\begin{document}
Hello, LaTeX!
\end{document}
然后在 terminal 里执行:
bash复制xelatex test.tex
如果同目录下生成了 test.pdf,说明整套工具链本身是通的。这一步做完再进 VS Code,后面排查问题会轻松很多,因为你已经能把“编译器坏了”和“插件配置错了”这两类问题区分开了。
2.4 VS Code 侧只需要装一个核心插件
VS Code 本体没什么好说的,去官网下载、安装、登录同步账号即可,唯一建议是顺手换个中文界面语言包,减少初期的心理摩擦。
LaTeX 相关的插件虽然不少,但我实际用下来,核心只需要一个:LaTeX Workshop。这个插件维护非常活跃,功能覆盖了从编译、预览、语法检查到正反向同步的全链条,没必要同时装一堆功能重叠的插件,反而容易互相打架。
在 VS Code 的插件市场里搜索 LaTeX Workshop,认准作者是 James Yu 的那个,装好就够用了。装完插件之后,先打开一个 .tex 文件,右侧可能会出现一个很简陋的预览面板,不要慌,那是 LaTeX Workshop 内置的 PDF 查看器,真正的编译配置还需要我们按照下面章节来做。
3. 配置 LaTeX Workshop 的实操细节
3.1 核心配置项逐行拆解
LaTeX Workshop 的默认配置其实已经能跑了,默认会调用 latexmk 进行编译,PDF 预览用内置查看器。但实际用起来有几个痛点必须自己调:
- 中文支持:默认的 pdflatex 处理中文会报错,需要切换到 xelatex。
- 编译干净程度:latexmk 默认会保留中间文件,不清理的话目录会越来越乱。
- 自动编译触发时机:默认保存时才编译,但有时候你希望手动精确定义编译方式,避免写半个公式被自动编译打断。
在 VS Code 里按 Ctrl+Shift+P(macOS 是 Cmd+Shift+P),输入 settings,打开用户设置 JSON,把下面这段配置放进去:
json复制{
"latex-workshop.latex.recipes": [
{
"name": "XeLaTeX",
"tools": [
"xelatex"
]
}
],
"latex-workshop.latex.tools": [
{
"name": "xelatex",
"command": "xelatex",
"args": [
"-synctex=1",
"-interaction=nonstopmode",
"-file-line-error",
"-pdf",
"%DOC%"
]
}
],
"latex-workshop.view.pdf.viewer": "tab",
"latex-workshop.latex.autoBuild.run": "onSave",
"latex-workshop.latex.clean.fileTypes": [
"*.aux",
"*.log",
"*.fls",
"*.out",
"*.synctex.gz",
"*.fdb_latexmk"
]
}
这段配置做了四件事,我来逐个解释原因。
recipe 里只保留了一个编译方案 XeLaTeX。为什么不用默认的 latexmk?latexmk 是个自动化调度工具,会自动判断用 pdflatex 还是 xelatex,但它在中文文档的识别上偶尔会自作主张,而且它的清理策略有时候比较激进或者不够彻底。直接指定 xelatex 则稳定得多,尤其对于中文 LaTeX 用户来说,xelatex 就是最优先的选择。
tools 里的参数解释一下:
- -synctex=1:生成 synctex 文件,这是正反向同步的基础,后面会讲。
- -interaction=nonstopmode:遇到错误时不要停下来等待用户输入。这个参数在自动化环境里是保命项,否则编译遇到一个错误就会卡在那里,看似“卡死”其实在等你按键。
- -file-line-error:让编译器以“文件名:行号:错误信息”的格式输出错误,这样 VS Code 才能把报错定位到具体行。
- -pdf:直接产出 PDF 文件。严格说 xelatex 默认就是产出 PDF,写上这个参数是显式声明,以防未来默认行为变化。
view.pdf.viewer 设成 tab,会让 PDF 在 VS Code 里以标签页形式展示。如果你有双显示器,可以考虑把 viewer 设成 browser,然后在浏览器里预览 PDF,这样编辑器区全屏写作,PDF 放副屏,体验非常舒服。区别只是个人偏好,不影响编译。
autoBuild.run 设为 onSave,保存时自动编译。我最开始开的是 onFileChange,结果每次输入停顿就被编译一次,浪费性能还烦人。onSave 的节奏比较适中,写一个段落点一次保存,编译一次,反馈足够快。
3.2 正反向同步是这套配置的灵魂
很多教程只讲怎么编译出 PDF,却忽略了 LaTeX 写作里最影响效率的一个功能:正反向同步。
正向同步指的是,你在 .tex 文件的某一处,通过快捷键直接跳转到 PDF 里对应的位置,方便快速检查这一处排版出来的效果。反向同步则反过来——你在 PDF 预览里双击某一行文字,编辑器自动跳到对应的 .tex 源码位置。
LaTeX Workshop 默认提供这两个功能:
- 正向同步:Ctrl+Alt+J(macOS 是 Cmd+Alt+J)
- 反向同步:在 PDF 预览里 Ctrl+点击(macOS 是 Cmd+点击)
这个功能能正常工作,依托于前面 tools 里加的 -synctex=1 参数。编译时生成的 .synctex.gz 文件保存了 tex 源文件和 PDF 输出之间的映射关系。
这里有一个很多教程不会提的细节:第一次编译完成后,你打开 PDF,然后点击反向同步,可能会觉得它跳得不准。这不是 bug,而是因为编译是在保存时触发的,你打开 PDF 时它可能还没更新完。等编译状态栏转完再去点击,定位就准了。另外,如果你用 latexmk 编译,中间文件清理时把 .synctex.gz 删了也会导致同步失效,所以我的 clean.fileTypes 配置里保留了 .synctex.gz,只在必须清理时才手动清。
3.3 Windows 用户常踩的环境变量坑
如果你在 Windows 上装完 TeX Live,打开 VS Code,发现 LaTeX Workshop 一直报错,说什么“Recipe terminated with fatal error”,但你在命令行里手动编译又是好的,那八成是 PATH 没配置对。
TeX Live 安装时默认会把自己的 bin 目录加进 PATH,但有一种情况例外:你在安装 TeX Live 之前就已经打开了 VS Code,这会导致 VS Code 的进程里继承的 PATH 环境变量是旧的值,读不到新加入的 TeX 路径。解决办法很简单:完全关闭 VS Code 再重新打开,确认右下角没有残留进程就行。
如果你手动设置过 PATH 还是不行,检查一下 TeX Live 的 bin 路径是否真实存在。Windows 下一般是 D:\texlive\2024\bin\windows 这样的结构,不同年份版本号不同。在 PowerShell 里可以执行:
powershell复制where.exe xelatex
如果能看到 xelatex.exe 的完整路径,说明 PATH 已经正确。如果只显示“找不到”的提示,就把 bin 目录手动加到系统环境变量里去。
macOS 上以 MacTeX 安装的话一般不会遇到这问题,Linux 装完 texlive-full 后在终端里也正常,但如果是从源码或者 .deb 单包安装,注意某些发行版把可执行文件放进了 /usr/bin 而不是 /opt/texlive 的标准路径,这时候 whereis xelatex 看一眼就知道问题在哪。
4. 从零编译第一个中文文档
4.1 写一个最小可编译的中文文档
环境配置好之后,直接从最小例子开始跑通。新建一个文件夹,比如 latex-demo,在里面新建一个 main.tex 文件,复制下面的内容:
latex复制\documentclass[UTF8]{ctexart}
\usepackage{amsmath}
\usepackage{hyperref}
\title{第一个中文 LaTeX 文档}
\author{你的名字}
\date{\today}
\begin{document}
\maketitle
\section{为什么用 xelatex}
这篇文章的全部内容都在测试 xelatex 对中文的支持。CTeX 宏包配合 xelatex 编译,中文排版没有任何障碍。
\section{一个公式}
麦克斯韦方程组是经典电磁理论的核心,其微分形式如下:
\begin{equation}
\begin{aligned}
\nabla \cdot \mathbf{E} &= \frac{\rho}{\varepsilon_0} \\
\nabla \cdot \mathbf{B} &= 0 \\
\nabla \times \mathbf{E} &= -\frac{\partial \mathbf{B}}{\partial t} \\
\nabla \times \mathbf{B} &= \mu_0 \mathbf{J} + \mu_0 \varepsilon_0 \frac{\partial \mathbf{E}}{\partial t}
\end{aligned}
\end{equation}
\end{document}
这里第一行的 \documentclass[UTF8]{ctexart} 是中文文档的关键:ctexart 是 CText 宏包提供的文档类,专门处理中文排版,UTF8 选项告诉它源码文件是 UTF-8 编码。如果用的是 article 文档类然后自己加 ctex 宏包,也可以,但更推荐直接用 ctexart,因为标题、章节、目录这些都会自动按中文习惯排版。
保存文件之后,因为前面配置了 onSave 自动编译,LaTeX Workshop 会立刻调用 xelatex 编译这个文档。编译成功后,PDF 预览会自动打开。
4.2 编译产物与文件清理的理解
编译完之后,你会看到目录里除了 main.tex 和 main.pdf,还多了一堆 .aux、.log、.out、.synctex.gz 之类的文件。这些是什么?简单说,LaTeX 编译是一个多趟扫描的过程:
- 第一趟扫描源代码,生成 .aux 文件,记录交叉引用和目录信息。
- 第二趟读取 .aux 文件,解析引用编号,然后才真正把交叉引用和目录填入文档。
- 对带参考文献的文档,还需要跑 bibtex 或者 biber,再重复两趟。
所以,明明只写了“见第 2 节”,为什么编译一遍之后显示的是“见第 ?? 节”?因为第一趟编译时编号还没计算出来,第二趟才补上。这就是为什么 LaTeX 有个经典操作——“多编译两遍就好了”。
.aux 文件存交叉引用、目录索引,.log 文件存编译日志,.synctex.gz 存源码和 PDF 的映射关系,.out 存 hyperref 宏包的内部信息,.fls 和 .fdb_latexmk 是 latexmk 的使用记录。这些东西的主要用途是辅助编译,不该被提交到 Git 仓库里,所以在 .gitignore 里可以加上一行:
gitignore复制*.aux
*.log
*.fls
*.out
*.synctex.gz
*.fdb_latexmk
main.pdf
PDF 要不要提交版本库,看团队习惯,如果是用 Overleaf 协作,PDF 可以生成时不提交;如果是给导师或者同事预览,留着方便。
4.3 配好之后再进阶:多文件文档与主文件设定
写完单文件的文档后,很快会遇到一个问题:文档长了,比如一篇毕业论文有七八个章节,每个章节几百行,全部塞在一个 .tex 文件里会非常难维护。这时候就需要拆成多个文件,用 \input 或者 \include 把子文件导入主文件。
新建一个 chapter_intro.tex:
latex复制\section{引言}
这里是引言内容,可以随意写一些中文段落,测试多文件编译。
然后在 main.tex 的 \begin{document} 和 \end{document} 之间加上:
latex复制\include{chapter_intro}
LaTeX Workshop 处理多文件编译有一个隐藏逻辑:它在保存任何一个被 \include 的 .tex 文件时,都会自动找主文件来编译。但这里有个坑——如果 LaTeX Workshop 的“主文件识别”弄错了,或者你的主文件不在当前打开文件的同一目录,它可能编错文件。
解决方法有两个。第一,在子文件的最顶部加上一行魔法注释,告诉 LaTeX Workshop 主文件是哪个:
latex复制% !TeX root = main.tex
第二,在 settings.json 里直接指定 magic 注释的解析方式。虽然 LaTeX Workshop 默认支持这种注释,但我见过不少人因为文件编码问题(比如 UTF-8 BOM)导致这行注释识别失败,所以我还是习惯在 settings.json 里对应配一下:
json复制"latex-workshop.latex.recipe.default": "lastUsed",
"latex-workshop.latex.magic.args": [
"-output-directory=out",
"%DOC%"
]
其中 -output-directory=out 是把编译中间文件和 PDF 输出到独立的 out 目录,这样源文件目录能始终保持干净。需要注意的是,加了输出目录参数后,PDF 的路径会发生变化,LaTeX Workshop 会自动处理这个路径,不需要你手动去打开 PDF。如果你自己也用命令行手动编译,记得保持一致,否则 synctex 会找不到映射关系。
5. 高频问题与排查方法实录
5.1 常见报错速查表
我把自己在实际使用中,以及在帮别人排查时遇到的高频问题整理成一张速查表,方便对照处理:
| 报错现象 | 根因 | 解决方式 |
|---|---|---|
| Recipe terminated with fatal error. | 编译命令找不到,多半是 PATH 环境变量没配好 | 终端里敲 xelatex --version 验证,检查 TeX Live bin 目录是否在 PATH |
| ! LaTeX Error: File `xxx.sty' not found. | 缺少对应宏包 | 安装时选 full 方案基本不会遇到;在线安装可用 tlmgr install xxx 补齐 |
| ! Package ctex Error: CTeX font set `fandol' is unavailable. | 中文字体缺失或字体配置不对 | 在 Windows 上安装 texlive 时已在默认字体集里;Linux 上安装 fonts-noto-cjk 后重新编译 |
| Undefined control sequence. | 源码里用了未定义的命令或者拼写错误 | 查看日志里最接近错误的代码行,修正命令拼写 |
| Emergency stop. | 编译错误太严重,走到崩溃状态 | 检查最开始的错误,通常第一个错误才是真正原因,后面的错误信息大多是连锁反应 |
| ! Package hyperref Error: Token not allowed in a PDF string. | hyperref 宏包里用了特殊命令(比如数学符号)在章节标题里 | 在 \section 之类命令的可选参数里改用纯文本,比如 \section[标题文本]{标题文本 $\alpha$} |
| Missing $ inserted. | 在数学环境外用了数学命令 | 检查当前是否处于 math mode,或者命令本身是否需要 $ 包裹 |
| SyncTeX 无法跳转或者跳转位置不准 | 缺少 .synctex.gz 文件,或文档没编完 | 确认编译参数里含 -synctex=1,删除旧中间文件后重新编译两遍 |
| 编译很慢,每次保存都要等好几秒 | 文档过大或者字体配置里用了复杂方案 | 把 autoBuild.run 改为 onSave;多次点击保存不要切走;将不需要编译的章节临时注释掉 |
5.2 参考文献不更新的排查与处理
正文里写 \cite{xxx},编译完发现问题区显示 [?],这是新手最常见的一个问题。原因还是前面说的多趟编译机制:正文引用和参考文献列表之间存在依赖关系,需要来回多跑几趟。
用 xelatex + bibtex 的方式,标准编译顺序是:
bash复制xelatex main.tex
bibtex main
xelatex main.tex
xelatex main.tex
第一趟生成 .aux 文件,bibtex 从 .aux 里提取 \cite 信息,去 .bib 文件中找对应条目,生成 .bbl 文件,第二趟和第三趟把参考文献列表和正文引用编号整合到 PDF 里。
如果手动敲这四步太烦,可以把 LaTeX Workshop 的 recipe 改成用 latexmk,它自动判断引用和文献是否需要重跑。不过我自己更习惯维护一个自定义 recipe,把 xelatex、bibtex、xelatex、xelatex 按顺序串起来。
在 settings.json 里改 recipe:
json复制{
"name": "XeLaTeX -> BibTeX -> XeLaTeX*2",
"tools": [
"xelatex",
"bibtex",
"xelatex",
"xelatex"
]
}
然后在 tools 里补一个 bibtex 的定义:
json复制{
"name": "bibtex",
"command": "bibtex",
"args": [
"%DOC%"
]
}
这里有个细节:bibtex 命令的参数应该是 .tex 文件的主文件名,不包含扩展名,%DOC% 宏正好满足这个要求。如果你用的是 biblatex + biber 方案,把命令换成 biber 即可。
5.3 中文环境的字体与 UTF-8 编码问题
用 VS Code 写 LaTeX,默认会自动保存为 UTF-8 编码,一般不会出现乱码。但如果你是从网上复制了一段代码,而那段代码本身是在 Windows 记事本里用 GBK 编码保存过的,粘贴到 VS Code 时就可能出现乱码。
处理方式非常简单:在 VS Code 右下角点击编码信息,选择“通过编码重新打开”,再选 UTF-8,就能把内容恢复成正确的状态,然后再保存一遍。
字体方面,xelatex 配合 ctex 宏包,在 Windows 和 macOS 上一般会自动选择系统中文字体,不需要额外配置。Linux 上如果没有中文字体,编译会报错,安装 Noto CJK 字体即可:
bash复制sudo apt install fonts-noto-cjk
另外,如果你有特定的字体偏好,比如要全文都用宋体、标题用黑体,可以在导言区指定字体设置:
latex复制\setCJKmainfont{SimSun}
\setCJKsansfont{SimHei}
这种情况下注意字体名要严格等于系统里字体的实际名称,Windows 上可以通过右键字体文件查看完整名称,macOS 上可以用 fc-list 命令列出所有已安装字体。
5.4 性能优化:大文档的编译提速经验
写大文档(比如毕业论文或者书籍),每次编译都要花掉好几秒甚至十几秒,这是个很烦人的问题。我实际用下来有几个提速技巧:
第一,在调试阶段只编一个章节。把主文件里没有在改的 \include 注释掉,只保留当前章节,可以显著缩短编译时间。但要注意,注释掉章节会让交叉引用和页码发生变化,所以最终交付前必须完整编一遍。
第二,用 latexmk 的 -pdf -xelatex 方式启动常驻模式。它的增量编译逻辑会跳过没变化的文件,对多章节文档效果明显。在 LaTeX Workshop 的 tools 里可以换成 latexmk,但注意要配合前面的 -synctex=1 参数,否则会失去跳转功能。
第三,改一次只保存一次。VS Code 的自动保存很多时候触发过于频繁,一个段落没写完整就开始编译,浪费 CPU。可以把 autoSave 关掉,或者设成 onFocusChange——焦点离开编辑器窗口时才保存,正好符合“写完一个段落再看一眼效果”的节奏。
第四,次要用到的宏包尽量局部加载而不是全放导言区。虽然 LaTeX 宏包的加载本身不慢,但有些宏包会调字体、会定义大量命令,大型文档导言区如果堆了几十个宏包,每次编译的解析时间也会线性增长。拿不准的时候就把要用的宏包注释一部分,只留必要的那几个,文档逻辑没受影响就行。
6. 这套配置的实际使用感受
我刚从 TeXstudio 换到 VS Code 的时候,说实话第一周不太适应。VS Code 对 LaTeX 的补全和提示没有 TeXstudio 那么“专一”,它本质上是个通用编辑器,LaTeX 的支持全靠插件。但适应期过了之后,你就能感受到这种通用架构的好处——你可以开四个终端窗口、两个 PDF 预览、一个 markdown 文档、一个代码文件,在同一套编辑器里完成所有写作和交叉任务。
VS Code 的 Git 集成也让写作变得安全很多。LaTeX 文档本质上就是文本文件,配合 Git 做版本管理,写废了随时回滚。我习惯在每章写到一个稳定状态时 commit 一次,有段时间写论文改到第三版,对比新旧版本的时候真是救了大命。
最后再分享一个跟排版工具本身无关的小习惯:写完一个文档之后,手动跑一遍清理命令,把中间文件全删掉,只保留 .tex、.bib、.pdf 和图片目录。这样既便于备份,也方便把项目文件打包发给别人。压缩包不至于莫名其妙多出几百个 aux 文件,对方打开就能直接编译。这个方法比较朴素,但确实是我这几年用下来最不容易出错的工作流。
