乐趣区

关于javascript:记录从vuecli打包库迁移到rollup打包

前言

最近的我的项目要实现一个利落拽的性能,于是乎须要把原来的模块粒度划分的更小,须要更多更细的组件,而组件打包对前端来说就是要打包成库,因为我的项目是 vue 我的项目,之前始终用 vuecli 来打包(vuecli 构建指标(库)),然而当初要打包很多组件的时候,vuecli 的弊病就显示进去了,打包速度太慢,只有一个入口文件,没有依赖其余的包的状况下,打包竟然要耗时长达 40+s(也可能是自己电脑垃圾的起因),如果是我的项目里原来的组件,每个组件打包要耗时 120s 以上,那么所有组件总的耗时加起来得要小半个小时了。于是我想晋升下打包速度,从 vuecli 下手是不可能了,那就须要寻求其余的构建工具了,想起 vue3 的 vite,底层用的就是 rollup,查了下相干的材料,rollup 几乎就是为了打包库而生的!

筹备工作

决定用 rollup 了,看了下相干文档,开始干!
踩坑中 …

  1. 装置最新版本的rollup-plugin-vue,打包后渲染不进去报错vue.openBlock is not a function,显然是因为 vue 版本不对,查看了下插件材料,发现 6.0+ 以上是反对 vue3 的,vue2 得装置 6.0 以下的版本
  2. 因为有个组件 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.js
    src/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.js
    import 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;
    
退出移动版