1

foreword

The recent project needs to implement a drag-and-drop function, so it is necessary to divide the original module granularity into a smaller granularity, requiring more and finer components, and component packaging is to be packaged into a library for the front end, because the project is a vue project , I have been using vuecli to package ( vuecli build target (library) ), but now when many components are to be packaged, the disadvantages of vuecli are revealed, the packaging speed is too slow, there is only one entry file, and there is no dependence on other packages Next, packaging actually takes up to 40+s (it may also be the reason for my computer garbage). If it is the original component in the project, it takes more than 120s to package each component, then the total time-consuming of all components adds up to It's about half an hour. So I want to improve the packaging speed. It is impossible to start with vuecli, so I need to find other construction tools. I think of vue3's vite, the bottom layer is rollup, I checked the relevant information, rollup is simply for packaging libraries Born!

Preparation

Decided to use rollup, read the relevant documents, and started!
Step into the pit...

  1. Install the latest version rollup-plugin-vue , after packaging, the rendering fails to report an error vue.openBlock is not a function , obviously because the vue version is wrong, check the plug-in information, and find that vue3 is supported above 6.0+, vue2 has Install a version below 6.0
  2. Because there is a component sync-tree that uses the render function, which uses the jsx syntax, the error is reported as follows when packaging:

     [!] (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)

    The error code is in rollup-plugin-vue. By checking the related issues, I found that some people have encountered the same problem as me, but unfortunately this problem has not been solved. By querying the information of various communities, many people say that as long as the preset of babel's jsx is configured, the configuration is as follows:

     babel({
      presets: ["@vue/babel-preset-jsx"],
    })

    I did the same, but still the same error.
    Later, I found an article that documents the rollup packaged vue component library with github source code examples, cloned it down and ran it, and it can be successfully built.
    Through comparison and screening, it is found that it is caused by the version of this package @rollup/plugin-babel , v5.2.1 is ok, v5.2.2 will report an error, and by comparing the source code submission log, it is found that this version of v5.2.2 has been modified The filter method has added the stripQuery method to filter the previous path, such as --- 4e9f99d58cd1931096375d81ccad2dfd F:\work\front-end\study\rollup\src\comp\test.vue?rollup-plugin-vue=script.js this path contains .js without filtering before, so it can be compiled successfully, but after filtering ? , the path becomes F:\work\front-end\study\rollup\src\comp\test.vue , .js is not in the compilation scope, so the compilation error will be reported. So how to solve this problem, just configure in babel extensions add .vue configuration, the configuration is as follows:

     extensions:['.js', '.jsx', '.es6', '.es', '.mjs','.vue'],

    Then after adding css, it reported an error

     [!] (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)

    The prompt css part reported an error, the reason is that I configured css to be packaged separately in the plugin vue in rollup, not packaged into js

     vue({
       css: false, // 把单文件vue中的样式,插入到html的style标签中,
       compileTemplate: true,
     })

    The reason is similar to the error reported by jsx, because babel adds query filtering, resulting in the file path becoming F:\work\front-end\study\rollup\src\my-component.vue , but css does not need babel to compile, so we need to check out the css part, by viewing the babel source code It is found that the filter part is composed of two parts, one is the suffix in the extension, and the other is the filter method defined by yourself

     const userDefinedFilter = typeof customFilter === 'function' ? customFilter : pluginutils.createFilter(include, exclude);
    filter = id => extensionRegExp.test(stripQuery(id).bareId) && userDefinedFilter(id);

    As long as you write your own filtering method to exclude css, the configuration is as follows:

     filter: id=>{
       console.log(id)
       return /(\.js|\.jsx|\.es6|\.es|\.mjs)$/.test(id)
     }

    Attach the complete rollup.config.js file content

     // 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;

juan26
521 声望19 粉丝