前言
最近的我的项目要实现一个利落拽的性能,于是乎须要把原来的模块粒度划分的更小,须要更多更细的组件,而组件打包对前端来说就是要打包成库,因为我的项目是vue我的项目,之前始终用vuecli来打包(vuecli构建指标(库)),然而当初要打包很多组件的时候,vuecli的弊病就显示进去了,打包速度太慢,只有一个入口文件,没有依赖其余的包的状况下,打包竟然要耗时长达40+s(也可能是自己电脑垃圾的起因),如果是我的项目里原来的组件,每个组件打包要耗时120s以上,那么所有组件总的耗时加起来得要小半个小时了。于是我想晋升下打包速度,从vuecli下手是不可能了,那就须要寻求其余的构建工具了,想起vue3的vite,底层用的就是rollup,查了下相干的材料,rollup几乎就是为了打包库而生的!
筹备工作
决定用rollup了,看了下相干文档,开始干!
踩坑中...
- 装置最新版本的
rollup-plugin-vue
,打包后渲染不进去报错vue.openBlock is not a function
,显然是因为vue版本不对,查看了下插件材料,发现6.0+以上是反对vue3的,vue2得装置6.0以下的版本 因为有个组件sync-tree里有用到render函数,外面用到了jsx语法,在打包的时候遇到了报错如下:
[!] (plugin commonjs) SyntaxError: Unexpected token (6:12) in F:\work\front-end\study\rollup\src\comp\test.vue?rollup-plugin-vue=script.jssrc/comp/test.vue?rollup-plugin-vue=script.js (6:12)4: render(h){5: return (6: <span class="comp">test-12311</span> ^7: )8: }SyntaxError: Unexpected token (6:12) in F:\work\front-end\study\rollup\src\comp\test.vue?rollup-plugin-vue=script.js at Parser.pp$4.raise (F:\work\front-end\study\rollup\node_modules\rollup\dist\shared\rollup.js:19844:13) at Parser.pp$9.unexpected (F:\work\front-end\study\rollup\node_modules\rollup\dist\shared\rollup.js:17138:8)
报错代码是在rollup-plugin-vue,通过查阅相干的issues发现也有人遇到了和我一样的问题,然而遗憾的是没有解决这个问题。通过查问各种社区的材料,很多人都说只有配置了babel的jsx的preset就能够,配置如下:
babel({ presets: ["@vue/babel-preset-jsx"],})
我也这么配置了然而还是一样报错。
起初找到了一篇文档带github源码示例的rollup打包vue组件库的文章,clone下来跑了一下果然是能够胜利构建的。
通过比拟和筛查发现是因为@rollup/plugin-babel
这个包的版本引起的,v5.2.1是能够的,v5.2.2就会报错了,通过比拟源码提交日志发现v5.2.2这个版本批改了filter的办法,增加了stripQuery
办法来过滤? 后面的门路,比方F:\work\front-end\study\rollup\src\comp\test.vue?rollup-plugin-vue=script.js
这个门路之前没有过滤就是蕴含.js 的,所以能够编译胜利,然而过滤了? 之后,这个门路就变成了F:\work\front-end\study\rollup\src\comp\test.vue
,.js不在编译范畴内,所以才会编译报错。那怎么解决这个问题呢,只有在babel中配置extensions
增加.vue 的配置就能够了,配置如下:extensions:['.js', '.jsx', '.es6', '.es', '.mjs','.vue'],
而后增加了css之后又报错了
[!] (plugin babel) SyntaxError: F:\work\front-end\study\rollup\src\my-component.vue?rollup-plugin-vue=styles.0.css: Unexpected token (1:0)> 1 | .test[data-v-103b65c0] { | ^ 2 | color: red; 3 | } 4 | .test .comp[data-v-103b65c0] {src/my-component.vue?rollup-plugin-vue=styles.0.css (1:0)SyntaxError: F:\work\front-end\study\rollup\src\my-component.vue?rollup-plugin-vue=styles.0.css: Unexpected token (1:0)> 1 | .test[data-v-103b65c0] { | ^ 2 | color: red; 3 | } 4 | .test .comp[data-v-103b65c0] { at instantiate (F:\work\front-end\study\rollup\node_modules\@babel\parser\src\parse-error\credentials.js:61:22) at toParseError (F:\work\front-end\study\rollup\node_modules\@babel\parser\src\parse-error.js:58:12)
提醒css局部报错了,起因是我在rollup中的插件vue中配置了css独自打包,不打包到js中
vue({ css: false, // 把单文件vue中的款式,插入到html的style标签中, compileTemplate: true, })
起因和jsx报错差不多,因为babel加了query的过滤,导致文件门路变成了
F:\work\front-end\study\rollup\src\my-component.vue
,然而css是不须要babel编译的,所以咱们须要排查掉css这部分,通过查看babel源码发现filter局部是由两局部形成的,一个是extension中的后缀,一部分是本人定义的过滤办法const userDefinedFilter = typeof customFilter === 'function' ? customFilter : pluginutils.createFilter(include, exclude);filter = id => extensionRegExp.test(stripQuery(id).bareId) && userDefinedFilter(id);
只有本人写过滤办法把css排除即可,配置如下:
filter: id=>{ console.log(id) return /(\.js|\.jsx|\.es6|\.es|\.mjs)$/.test(id) }
附上残缺的rollup.config.js文件内容
// rollup.config.jsimport resolve from "@rollup/plugin-node-resolve";import vue from "rollup-plugin-vue";import babel from "@rollup/plugin-babel";import commonjs from "@rollup/plugin-commonjs";import image from "@rollup/plugin-image";import scss from "rollup-plugin-scss";import { terser } from "rollup-plugin-terser";import CleanCss from "clean-css";import alias from "@rollup/plugin-alias";import injectProcessEnv from "rollup-plugin-inject-process-env";const fs = require("fs");const path = require("path");const dotenv = require("dotenv");const dotenvExpand = require("dotenv-expand");var myEnv = dotenv.config();dotenvExpand.expand(myEnv);const myEnvObj = myEnv.parsed;const outputName = "myComponents";const extensions = [".scss", ".js", ".vue"];const customResolver = resolve({ extensions,});const config = { input: "./src/wrapper.js", // 必须,入口文件 output: { // 必须,输入文件 (如果要输入多个,能够是一个数组) file: `lib/${outputName}.min.js`, format: "umd", name: outputName, // exports: "named", // 输入多个文件 globals: { vue: "Vue", // 通知rollup全局变量Vue即是vue }, }, external: ["vue", "hui", "vuex"], // 内部依赖 plugins: [ vue({ css: false, // 把单文件vue中的款式,插入到html的style标签中, compileTemplate: true, }), resolve({extensions}), babel({ presets: ["@vue/babel-preset-jsx"], babelHelpers: 'bundled', // exclude: 'node_modules/**', extensions:['.js', '.jsx', '.es6', '.es', '.mjs','.vue'], filter: id=>{ console.log(id) return /(\.js|\.jsx|\.es6|\.es|\.mjs)$/.test(id) && !/node_modules/.test(id) } }), commonjs(), image(), scss({ output: function (styles, styleNodes) { const compressed = new CleanCss().minify(styles).styles; fs.writeFileSync( path.resolve(__dirname, `lib/${outputName}.css`), compressed ); }, }), terser({ keep_fnames: false, }), // 压缩 alias({ entries: { "@comp": path.resolve(__dirname, "src/comp"), }, customResolver, }), injectProcessEnv({ NODE_ENV: "production", ...myEnvObj, }) ],};export default config;