进阶 unplugin.unjs.io 2026-10-08 10:00:35 · 6 阅读

第10章 unplugin-preprocessor-directives 预处理器指令插件详解

13114 unplugin-preprocessor-directives 英文 | 简体中文 安装 bash npm i unplugin-preprocessor-directives 注意:此插件应置于配置中的所有其他插件之前,以确保预处理器指令优先被处理。 Vite ts // vite.config.ts import PreprocessorDirectives from 'unplugin-preprocessor-directives/vite' export default defineConfig({ plugins: [ PreprocessorDirectives({ /* options */ }), // 应为第一个插件 ], }) Rollup 示例:playground/ Rollup ts // rollup.config.js import PreprocessorDirectives from 'unplugin-preprocessor-directives/rollup' export default { plugins: [ PreprocessorDirectives({ /* options */ }), ], } Webpack ts // webpack.config.js module.exports = { /* ... */ plugins: [ require('unplugin-preprocessor-directives/webpack')({ /* options */ }) ] } Nuxt ts // nuxt.config.js export default defineNuxtConfig({ modules: [ ['unplugin-preprocessor-directives/nuxt', { /* options */ }], ], }) 此模块适用于 Nuxt 2 和 Nuxt Vite。 Vue CLI ts // vue.config.js module.exports = { configureWebpack: { plugins: [ require('unplugin-preprocessor-directives/webpack')({ /* options */ }), ], }, } esbuild ts // esbuild.config.js import { build } from 'esbuild' import PreprocessorDirectives from 'unplugin-preprocessor-directives/esbuild' build({ plugins: [PreprocessorDirectives()], }) Rspack (⚠️ 实验性) ts // rspack.config.js module.exports = { plugins: [ require('unplugin-preprocessor-directives/rspack')({ /* options */ }), ], } 使用 定义符号 使用以下两个预处理器指令来定义或取消定义条件编译所需的符号: #define:定义一个符号。 #undef:取消定义一个符号。 使用 #define 来定义符号。当将该符号作为表达式传递给 #if 指令时,表达式将求值为 true,如下例所示: ts // #define VERBOSE // #if VERBOSE console.log('Verbose output version') // #endif 条件编译 #if:开启条件编译,仅当指定符号被定义且求值为 true 时,代码才会被编译。 #elif:关闭前一个条件编译,并根据指定符号是否被定义且求值为 true,开启新的条件编译。 #else:若前一个指定符号未定义或求值为 false,则关闭前一个条件编译并开启新的条件编译。 #endif:关闭前一个条件编译。 注意:默认情况下,使用 vite 的 loadEnv 函数基于 process.env.NODE_ENV 加载环境变量,并将编译符号作为条件。 ts // src/index.ts // #if DEV console.log('Debug version') // #endif // #if !MYTEST console.log('MYTEST is not defined or false') // #endif 可以使用 ==(相等)和 !=(不相等)运算符来测试 bool 值 true 或 false。true 意味着该符号已定义。语句 #if DEBUG 与 #if (DEBUG == true) 含义相同。可以使用 &&(与)、||(或)和 !(非)运算符来评估多个符号是否已定义。还可以使用括号对符号和运算符进行分组。 ts class MyClass { constructor() { // #if (DEBUG && MYTEST) console.log('DEBUG and MYTEST are defined') // #elif (DEBUG==false && !MYTEST) console.log('DEBUG and MYTEST are not defined') // #endif } } 错误、警告和信息消息 可指示编译器生成用户自定义的编译错误、警告和信息消息。 #error:生成一个错误,但不终止编译。 #warning:生成一个警告。 #info:生成一个信息消息。 ts // #error this is an error message // #warning this is a warning message // #info this is an info message 当然,也可以与条件编译结合使用: ts // #if DEBUG // #info Debug mode is on // #endif // #if !DEBUG // #info Debug mode is off // #endif #include 指令 可以使用 #include 指令将其他文件的内容包含到当前文件中。被包含的文件也会经过预处理器处理。 警告:#include 指令是一个编译时的文本替换工具,主要适用于以下场景: 在不同环境中包含不同的配置代码片段 与条件编译结合,根据编译条件包含不同的代码 共享需要预处理的代码片段 它不能也不应替代以下内容: JavaScript/TypeScript 的 import 或 require——用于模块化和依赖管理 CSS 的 @import——用于样式表模块化 HTML 模板系统或组件系统 如果只是想将代码模块化,请使用语言原生的模块系统。仅在需要编译时处理和条件包含时使用 #include。 该指令支持以下两种语法: ts // #include "path/to/file" 或 // #include 注意 循环引用:如果文件 A 包含文件 B,且文件 B 包含文件 A,系统将自动检测并防止循环引用,仅处理一次。 路径解析:相对路径相对于配置的工作目录 (cwd) 进行解析。 文件扩展名:可以包含任何类型的文本文件,不限于 .js 文件。 嵌套处理:被包含的文件会由预处理器完全处理,因此可以使用所有支持的指令。 自定义指令 可以使用 defineDirective 来定义自定义指令。 以内置指令为例: ts export const MessageDirective = defineDirective(context => ({ lex(comment) { return simpleMatchToken(comment, /#(error|warning|info)\s*(.*)/) }, parse(token) { if (token.type === 'error' || token.type === 'warning' || token.type === 'info') { this.current++ return { type: 'MessageStatement', kind: token.type, value: token.value, } } }, transform(node) { if (node.type === 'MessageStatement') { switch (node.kind) { case 'error': context.logger.error(node.value, { timestamp: true }) break case 'warning': context.logger.warn(node.value, { timestamp: true }) break case 'info': context.logger.info(node.value, { timestamp: true }) break } return createProgramNode() } }, generate(node, comment) { if (node.type === 'MessageStatement' && comment) return `${comment.start} #${node.kind} ${node.value} ${comment.end}` }, })) enforce: 'pre' | 'post' 指令的执行优先级: pre:尽可能早执行 post:尽可能晚执行

评论 (0)