尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Vue CLI 的 TypeScript 插件实战指南:@vue/cli-plugin-typescript 配置、缓存、并行编译与源码解析

Vue CLI 的 TypeScript 插件实战指南:@vue/cli-plugin-typescript 配置、缓存、并行编译与源码解析 Vue CLI 的 TypeScript 插件实战指南vue/cli-plugin-typescript 配置、缓存、并行编译与源码解析【免费下载链接】vue-cli️ webpack-based tooling for Vue.js Development项目地址: https://gitcode.com/gh_mirrors/vu/vue-cli本指南围绕 Vue CLI 官方 TypeScript 插件 vue/cli-plugin-typescript 展开系统讲解如何在 Vue CLI 项目中启用 TypeScript、配置tsconfig.json、与 Babel 协同工作以及插件内置的cache-loader缓存与thread-loader并行编译机制。读完本文你将掌握vue add typescript的完整流程、插件注入的 webpack-chain 规则并能结合源码理解ts-loaderfork-ts-checker-webpack-plugin的底层协作原理。一、插件概览TypeScript 支持的技术栈vue/cli-plugin-typescript是 Vue CLI 官方提供的 TypeScript 集成插件其核心思路是用TypeScript ts-loaderfork-ts-checker-webpack-plugin组合完成类型检查与转译ts-loader负责将 TypeScript 编译为 JavaScript默认开启transpileOnly仅做语法转译、不做类型检查以换取更快的构建速度fork-ts-checker-webpack-plugin在独立进程中执行类型检查避免阻塞 webpack 的编译主线程从而实现快的转译 完整的类型诊断两不误cache-loader与thread-loader分别提供增量缓存与多核并行进一步缩短开发与生产构建时间。从 package.json 可以看到该插件的直接依赖包含ts-loader^9.2.5、fork-ts-checker-webpack-plugin^6.4.0、thread-loader^3.0.0、babel-loader^8.2.2、types/webpack-env等而typescript、vue/cli-service、vue、cache-loader则被声明为peerDependencies其中cache-loader与vue-template-compiler为可选。二、安装方式2.1 新建项目时选择 TypeScript在vue create交互式创建项目时勾选TypeScript特性即可插件会随项目脚手架一并生成配置与模板文件。2.2 在已有项目中安装对已经创建好的项目执行vue add typescript该命令会将插件写入package.json的 devDependencies并调用其生成器generator执行一系列文件改造同时触发 prompts.js 中定义的一组交互式问题详见下一节。2.3 指定 TypeScript 版本自3.0.0-rc.6起typescript成为本插件的peerDependency意味着不再由插件锁定 TypeScript 版本而是由项目自身决定。你只需更新项目package.json中的typescript版本号即可自由选择 TypeScript 的特定版本peerDependencies 声明为typescript: 2兼容性广泛。三、交互式提示late-invoke 时的五个问题当插件被延迟安装即对已有项目执行vue invoke或vue add时会依次询问以下问题见 prompts.js提示项类型默认值含义classComponentconfirmtrue是否使用 class 风格组件语法vue-class-component/vue-property-decoratoruseTsWithBabelconfirm—是否让 Babel 与 TypeScript 协同工作modern mode、自动 polyfill、JSX 转译所必需convertJsToTsconfirmtrue是否将项目中所有.js文件转换为.tsallowJsconfirmfalse是否允许.js文件被一并编译skipLibCheckconfirmtrue是否跳过对所有声明文件.d.ts的类型检查应用项目推荐开启其中useTsWithBabel会直接决定生成的tsconfig.json中target的取值esnext或es5具体见第五节。四、生成器做了什么模板渲染、文件转换与联动兼容4.1 依赖注入generator/index.js 会向项目注入devDependenciestypescript版本取自插件自身 devDependencies若选择 class 组件语法Vue 2 项目注入vue-class-component与vue-property-decoratorVue 3 项目注入vue-class-component^8.0.0-0生成器声明module.exports.after vue/cli-plugin-router确保在 router 插件之后执行。4.2 渲染模板文件模板位于 generator/templateVue 2与 generator/template-vue3Vue 3包含src/main.ts由入口文件转换而来src/shims-vue.d.ts声明*.vue模块的类型src/shims-tsx.d.ts仅 Vue 2提供 JSX 的全局命名空间声明tsconfig.json项目 TypeScript 配置。对于 Vue 3由于 TSX 接口已在vue包的runtime-dom/types/jsx.d.ts中定义生成器会直接删除src/shims-tsx.d.ts见 generator/index.js#L64-L70避免重复声明。4.3 两种 shims 声明文件Vue 2 模板的 shims-vue.d.tsdeclare module *.vue { import Vue from vue export default Vue }Vue 3 模板的 shims-vue.d.ts 则改用DefineComponentdeclare module *.vue { import type { DefineComponent } from vue const component: DefineComponent{}, {}, any export default component }Vue 2 的 shims-tsx.d.ts 通过declare global扩展JSX.Element、JSX.ElementClass与JSX.IntrinsicElements使 TSX 在 Vue 2 下可获得完整类型支持。4.4 文件转换逻辑convert.jsgenerator/convert.js 在postProcessFiles阶段执行转换若convertJsToTs为true遍历所有文件删除存在同名.ts文件的.js文件其余.js文件直接重命名为.tsmain.js同理变为main.ts若为false仅将入口文件api.entryFile重命名为main.ts其余 JS 文件保持不变默认排除tests/e2e/目录以及*.config.js/*.rc.js这类配置文件若项目启用了e2e-webdriverio则仅排除配置文件。4.5 与其他插件的联动兼容在 late-invoke 场景下生成器会自动检测项目已有的插件并补齐 TypeScript 支持见 generator/index.js#L35-L55unit-mocha/unit-jest调用各自生成器的applyTS注入测试配置eslint调用 eslint 生成器的applyTS补充 TS 规则e2e-webdriverio调用其生成器的applyTS。五、tsconfig.json 配置详解插件模板生成的tsconfig.jsongenerator/template/tsconfig.json是 TypeScript 行为的核心配置生成时会根据用户选择动态注入选项配置项取值说明targetesnext配合 Babel/es5纯 tsc 转译由useTsWithBabel决定moduleesnext模块格式交由 webpack 处理stricttrue开启严格模式jsxpreserve保留 JSX 语法由后续 loader 处理importHelpers仅纯 tsc 模式为true通过tslib复用辅助函数减小产物体积moduleResolutionnode标准的 Node 解析策略experimentalDecorators选择 class 组件时为true支持装饰器语法allowJs选择后为true允许编译 JS 文件skipLibCheck选择后为true跳过声明文件类型检查esModuleInterop/allowSyntheticDefaultImportstrue兼容 CommonJS 默认导入forceConsistentCasingInFileNamestrue强制文件名大小写一致useDefineForClassFieldstrue使用原生 class fields 语义sourceMaptrue输出 source map便于调试baseUrl/paths.//*: [src/*]支持/xxx别名导入types按测试插件动态注入如webpack-env、mochachai、jest、wdio/*等libesnext、dom、dom.iterable、scripthost编译目标运行环境的类型库include覆盖src/**/*.ts、src/**/*.tsx、src/**/*.vue及tests/**/*.ts(x)exclude排除node_modules。此后你对 TypeScript 的任何定制都只需直接修改项目根目录的tsconfig.json。六、与 Babel 协同转译与 polyfill 的分工插件可以与vue/cli-plugin-babel同时使用且这是官方推荐的组合方式。在 index.js#L54-L59 中当检测到api.hasPlugin(babel)为真时会在ts与tsx两条规则中追加babel-loader。此时的分工如下ts-loader以transpileOnly: true模式把 TypeScript 编译为ES2015babel-loader接手剩余工作依据项目的 browserslist 目标自动注入 polyfillauto polyfill based on browser targets这种模式同时也是modern modevue-cli-service build --modern正常工作的前提——这也是 prompts 中useTsWithBabel选项说明required for modern mode, auto-detected polyfills, transpiling JSX的原因。七、缓存机制cache-loader插件默认启用cache-loader缓存存放在projectRoot/node_modules/.cache/ts-loader。在 index.js#L29-L41 中插件尝试require.resolve(cache-loader)成功则通过api.genCacheConfig(ts-loader, ...)生成缓存配置缓存 key 综合了ts-loader与typescript的版本号是否处于 modern buildVUE_CLI_MODERN_BUILD环境变量tsconfig.json内容。由于cache-loader是可选 peerDependency见 package.json当项目中不存在该包时插件会静默跳过缓存注入catch (e) {}不会报错。八、并行编译thread-loader当机器 CPU 核数大于 1 时插件默认启用thread-loaderindex.js#L43-L52将ts-loader放到 worker 线程池中执行。默认行为projectOptions.parallel为truevue.config.js未显式设置时且仅在production构建NODE_ENV production下启用线程若projectOptions.parallel是数字则作为 worker 数量传入{ workers: projectOptions.parallel }关闭方式在vue.config.js中设置parallel: false。重要限制当 TypeScript 与不可序列化的 loader options如正则表达式、Date、函数等组合使用时必须将parallel设为false。因为thread-loader通过序列化传递选项这类值无法被正确传给ts-loader可能导致难以排查的异常错误。九、注入的 webpack-chain 规则一览插件通过api.chainWebpackindex.js注入以下规则与插件供vue-cli-service inspect查看config.rule(ts)匹配\.ts$文件的规则config.rule(tsx)匹配\.tsx$文件的规则config.rule(ts).use(cache-loader)缓存 loaderconfig.rule(ts).use(thread-loader)并行 loaderproduction parallel 时config.rule(ts).use(babel-loader)与 Babel 协同时的转译 loaderconfig.rule(ts).use(ts-loader)核心 TypeScript 编译器config.plugin(fork-ts-checker)独立的类型检查插件。除此之外插件还会index.js#L9-L18在resolve.extensions中前置.ts与.tsx使无扩展名导入优先解析到 TS 文件当项目未配置多页!projectOptions.pages时将入口重置为./src/main.ts将插件自身的node_modules加入resolveLoader.modules前端确保 loader 解析正确。十、底层原理ts-loader 与 fork-ts-checker 的分工深入 index.js#L60-L107 可以看到关键配置ts-loader的options为{ transpileOnly: true, // 仅转译不做类型检查换取构建速度 appendTsSuffixTo: [\\.vue$], // 让 .vue 文件的 script langts 走 TS 编译 happyPackMode: useThreads // 线程模式下启用 happyPackMode与 worker 协同 }对tsx规则则通过.tap()将appendTsSuffixTo替换为appendTsxSuffixTo: [\\.vue$]使 Vue 单文件组件中script langtsx能正确编译类型检查完全交给fork-ts-checker-webpack-plugin其配置会自动探测 Vue 编译器优先使用vue/compiler-sfcVue 2.7否则回退到vue-template-compilerVue 2.6 及更低版本以支持.vue文件内的类型诊断extensions.vue.enabled: true诊断选项semantic: true始终开启语义检查syntactic: useThreads表示在线程模式下才做语法检查与happyPackMode的约束对应详见 ts-loader 文档说明 中的限制当设置了VUE_CLI_TEST环境变量vue-cli 自身测试场景时会跳过fork-ts-checker注入因为它与 jest cypress 的组合存在兼容问题见 index.js#L78-L80 注释。十一、迁移支持与注意事项11.1 从旧项目迁移仓库中还包含 migrator/index.js用于在升级 Vue CLI 版本时对既有 TypeScript 项目配置做兼容迁移配合vue upgrade使用。11.2 使用注意点版本约束该插件支持vue/cli-service3.x / 4.x / 5.x见 peerDependencies安装时需保证 Vue CLI 版本与之匹配parallel: false的适用场景一旦 loader 配置包含正则、Date、函数等非序列化选项务必关闭并行否则会出现诡异且难以定位的编译错误类型检查独立于转译由于转译与类型检查分离tsc在构建过程中不再执行完整类型检查——请依赖fork-ts-checker-webpack-plugin输出的诊断信息或在 CI 中额外运行vue-tsc之类的类型校验工具确保类型错误能被及时拦截。十二、验证与测试仓库为插件配备了完整的测试套件packages/vue/cli-plugin-typescript/tests覆盖默认 Vue 2 场景tsPluginDefault.spec.jsVue 3 场景tsPluginVue3.spec.js与 Babel 组合tsPluginBabel.spec.jsclass 组件语法tsPluginClassComponent.spec.js与 ESLint、E2E、单元测试插件的集成tsPluginESLint.spec.js、tsPluginE2e.spec.js、tsPluginUnit.spec.js。这些测试通过createTestProject等工具在真实项目中验证生成器输出与 webpack 构建结果是理解插件各配置项生效方式的最佳参考。结语vue/cli-plugin-typescript用一条清晰的规则链把 TypeScript 的转译、缓存、并行与类型检查分层解耦ts-loader专职转译、fork-ts-checker-webpack-plugin在独立进程做诊断、cache-loader与thread-loader分别优化增量与并行。理解这四者的边界与约束尤其是parallel的序列化限制你就能在 Vue CLI 项目中既获得类型安全又保持接近纯 JavaScript 的开发与构建体验。后续对 TypeScript 行为的定制统一通过项目根目录的tsconfig.json完成即可。【免费下载链接】vue-cli️ webpack-based tooling for Vue.js Development项目地址: https://gitcode.com/gh_mirrors/vu/vue-cli创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表