如何将.vue单文件组件编译为可配合Vue CDN使用的独立JS文件?
Vue单文件组件离线编译为可直接引入的JS文件方案
有两种常用的离线编译方案可实现需求,编译后的JS产物可直接配合Vue CDN在HTML中使用:
方案1:Vite库模式编译(推荐,配置简单,支持批量处理)
- 初始化项目
新建空文件夹后执行如下命令:npm init vite@latest vue-sfc-build -- --template vue cd vue-sfc-build npm install - 存放组件
把所有需要编译的.vue文件放入src/components目录,例如你示例的组件存为src/components/Component.vue。 - 修改Vite配置
编辑vite.config.js配置为库模式,将Vue设置为外部依赖不打入产物:import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' import { resolve } from 'path' export default defineConfig({ plugins: [vue()], build: { lib: { // 多入口配置,每个组件对应一个单独的输出文件 entry: { Component: resolve(__dirname, 'src/components/Component.vue'), // 其他组件继续在这里加即可 // OtherComp: resolve(__dirname, 'src/components/OtherComp.vue') }, name: 'Component', formats: ['umd'] }, rollupOptions: { external: ['vue'], output: { globals: { vue: 'Vue' } } } } }) - 执行编译
编译后的产物在npm run builddist目录下,每个组件对应单独的UMD格式JS文件,引入HTML后组件会直接挂载到window对象上,完全匹配你示例的用法:<script src="/path/to/Component.umd.js"></script> <script src="vue@next"></script> <script> const app = Vue.createApp({}) app.component("component", Component) app.mount("#app") </script>
方案2:官方编译工具自定义脚本编译(轻量无冗余)
如果不想搭建Vite项目,可以使用Vue官方的SFC编译工具编写简单Node脚本批量处理:
- 安装依赖
npm install @vue/compiler-sfc @vue/compiler-dom - 编写编译脚本
compile-sfc.jsconst fs = require('fs') const path = require('path') const { parse, compileTemplate, compileScript, compileStyle } = require('@vue/compiler-sfc') // 配置需要编译的.vue文件路径和输出路径 const inputPath = path.resolve(__dirname, 'Component.vue') const outputPath = path.resolve(__dirname, 'Component.js') const componentName = 'Component' // 读取并解析SFC文件 const sfcContent = fs.readFileSync(inputPath, 'utf-8') const { descriptor } = parse(sfcContent) const scopedId = 'data-v-' + Math.random().toString(16).slice(2, 8) // 编译模板得到render函数 const { code: renderCode } = compileTemplate({ source: descriptor.template.content, filename: path.basename(inputPath), scoped: descriptor.styles[0]?.scoped, id: scopedId }) // 编译script部分 const scriptRes = compileScript(descriptor, { filename: path.basename(inputPath), id: scopedId }) // 编译样式并生成注入代码 let styleInjectCode = '' if (descriptor.styles.length) { const { code: cssCode } = compileStyle({ source: descriptor.styles[0].content, filename: path.basename(inputPath), scoped: descriptor.styles[0].scoped, id: scopedId }) styleInjectCode = ` (function injectStyle() { const styleEl = document.createElement('style') styleEl.textContent = \`${cssCode}\` document.head.appendChild(styleEl) })() ` } // 拼接最终JS代码,挂载到全局对象 const scriptContent = scriptRes.content.replace('export default ', '') const finalCode = ` ${styleInjectCode} const ${componentName} = { ...${scriptContent}, ${renderCode.replace('export function render', 'render')} } window.${componentName} = ${componentName} ` fs.writeFileSync(outputPath, finalCode) - 执行脚本编译
执行后会生成可直接引入使用的node compile-sfc.jsComponent.js文件,用法和你示例完全一致。
内容的提问来源于stack exchange,提问作者Jatin Garg
相关产品推荐
相关产品推荐

