gogoend / blog

blogs, ideas, etc.
MIT License
9 stars 2 forks source link

将Anikyu的构建工具由Webpack迁移到Rollup #26

Open gogoend opened 4 years ago

gogoend commented 4 years ago

之前封Anikyu库的时候,主要是参考使用vue-cli脚手架构建应用程序的相关配置来进行的,因此之前的构建工具使用的是Webpack。但经过笔者的一些了解,很多库(例如,ECharts、Vue.js、Three.js)的构建工具并非Webpack,而是Rollup。当然也有部分库(例如,Axios)的构建工具使用的是Webpack。事实上,就在早前,Vue.js曾放出了Vue.js 3.0的相关消息,未来的项目将可能会使用一款名为Vite的工具来进行打包,而它基于的打包工具便是Rollup。

经过本人测试,相对使用Webpack打包的库而言,使用Rollup打包的库,冗余代码看起来更少一些。

下方分别是Axios和Vue两个库UMD包未压缩代码。

image Axios

image Vue

参考资料

10分钟快速入门rollup.js - 知乎 你还没有撸一个包扔到npm上? - 知乎

gogoend commented 4 years ago

移除相关依赖,修改构建配置

有关Anikyu的相关内容,可参考封装Anikyu时写的文章:尝试通过封装一个库(Anikyu)来学习JavaScript(ES6)相关特性以及相关构建工具,本文操作步骤基于v1.0.1 版本

首先,打开package.json看一下旧版本中相关开发依赖:

    "@babel/cli": "^7.8.3",
    "@babel/core": "^7.8.3",
    "@babel/polyfill": "^7.8.3",
    "@babel/preset-env": "^7.8.3",
    "@purtuga/esm-webpack-plugin": "^1.2.1",
    "babel-loader": "^8.0.6",
    "clean-webpack-plugin": "^3.0.0",
    "eslint": "^6.8.0",
    "webpack": "^4.41.5",
    "webpack-cli": "^3.3.10"

在此,Webpack相关依赖已经不再有用,可以直接删除,仅保留Babel与ESLint,然后再加入Rollup的相关依赖。

    "@babel/cli": "^7.8.3",
    "@babel/core": "^7.8.3",
    "@babel/polyfill": "^7.8.3",
    "@babel/preset-env": "^7.8.3",
    "eslint": "^6.8.0",
    "@rollup/plugin-babel": "^5.1.0",
    "@rollup/plugin-commonjs": "^14.0.0",
    "@rollup/plugin-node-resolve": "^8.4.0",
    "rollup": "^2.22.0",
    "rollup-plugin-terser": "^6.1.0"

此处可以了解一下与Rollup相关的依赖的作用:

  1. rollup Rollup打包工具的主要部分。
  2. @rollup/plugin-babel 用于将Babel整合到Rollup的插件。
  3. @rollup/plugin-commonjs 用于将CommonJS语法的模块转换为ES Module模块的插件。若不使用这一插件,在使用导出的UMD包时会报以下错误: image 虽然我们的项目中统一使用的是ES Module,然而某些依赖却是使用CommonJS语法写的,例如@babel/polyfill所用到的core-js: image 若不经过转换,在UMD包中会将require等语法原样保留,而浏览器原生不支持这种语法,因此需要对这种语法进行转换。
  4. @rollup/plugin-node-resolve 用于定位某些模块的插件。若不使用该插件,打包时会报错: image 对应的polyfill没有打入到最终生成的包中,低版本浏览器在执行时会报错: image
  5. rollup-plugin-terser 用于对代码进行压缩的插件。

然后,需要更改package.json上方scripts中的build脚本。由于Webpack已经不再使用,因此把脚本从原先的webpack-cli替换为rollup -c。 修改后如果我们迫不及待执行构建命令: image 将会提示“找不到入口模块rollup.config.js”。 在这里,rollup.config.js的角色和webpack.config.js是一致的,都是打包工具的配置文件。

同时,我们来看一下旧版本中的Webpack配置文件webpack.config.js。在配置的输出中,包含四个版本的Anikyu。 版本 UMD ESM
未压缩 anikyu.js anikyu.esm.js
已压缩 anikyu.min.js anikyu.esm.min.js

UMD版本用于老旧浏览器,通过script标签src属性引入;而ESM版本用于支持ES Module的浏览器,通过import语句引入。 我们迁移的最终目标,就是在保留Anikyu功能,不改动Anikyu库内部原有代码基础上,输出同样的这四种文件。

webpack.config.js可以先保留,之后可以参考这个文件进行输出配置(当然此时该文件也没用了,如果记下来相关输出配置,可以直接删除)。

接下来在项目根目录下新建rollup.config.js文件,内容如下:

import babel from '@rollup/plugin-babel';
import commonjs from '@rollup/plugin-commonjs';
import resolve from '@rollup/plugin-node-resolve';
import { terser } from "rollup-plugin-terser";

export default {
  input: './src/anikyu.js',
  output: [{
    file: `./dist/anikyu.js`,
    name: `Anikyu`,
    format: 'umd'
  },
  {
    file: `./dist/anikyu.min.js`,
    name: `Anikyu`,
    format: 'umd',
    plugins:[
      terser()
    ]
  },
  {
    file: `./dist/anikyu.esm.js`,
    format: 'es'
  },
  {
    file: `./dist/anikyu.esm.min.js`,
    format: 'es',
    plugins:[
      terser()
    ]
  }],
  plugins: [
    commonjs({
      extensions: ['.js'],
      ignoreGlobal: false,
      sourceMap: false,
    }),
    resolve({
      browser:true
    }),
    babel({
      exclude: 'node_modules/**'
    })
  ]
};

这里的相关配置参考自Three.js的构建配置文件下方有关输出的章节。(其中的某些参数配置笔者暂未仔细了解🌚)

此时若我们再执行npm run build,即可生成使用Rollup进行打包后的最终文件。这里产生了四个文件,分别对应上文所述的四个版本。


最终产生的diff变化可见:Pull Request

至此,Anikyu项目由Webpack构建到Rollup的构建便成功完成。 从文件体积上看,Rollup打包出来的版本显然更小一些。 image

gogoend commented 4 years ago

旧闻:过不去的一步

其实将Anikyu的构建工具迁移到Rollup是我一直都在尝试做的事情,今年四月就准备做,但由于当月太忙,就一直忘了,直到最近突然想起,便进行了一波尝试。 之前看了慕课网发布在知乎上的文章,遂一步步跟着做了下来,很完美。但后面发现文章里用到的Babel与Rollup版本其实是很早以前、已被deprecated的版本了;于是便研究如何从老版本升级到新版本,无奈中间总有一步过不去。(见:99fe673ad6a8d06848558a72d6717385a0edbc27) 这一版本的依赖包括:

  "devDependencies": {
    "@babel/cli": "^7.0.0",
    "@babel/core": "^7.0.0",
    "@babel/plugin-external-helpers": "^7.0.0",
    "@babel/plugin-transform-runtime": "^7.0.0",
    "@rollup/plugin-babel": "^5.1.0",
    "@rollup/plugin-commonjs": "^14.0.0",
    "@rollup/plugin-node-resolve": "^8.4.0",
    "babel-eslint": "^10.0.1",
    "babel-preset-env": "^1.7.0",
    "eslint": "^6.8.0",
    "rollup": "^2.22.0"
  }

这一版本Rollup及Babel的配置如下:

import resolve from '@rollup/plugin-node-resolve';
import babel from '@rollup/plugin-babel';
import commonjs from '@rollup/plugin-commonjs';

export default {
  input: './src/anikyu.js',
  output: [{
    file: `./dist/anikyu.js`,
    name: `Anikyu`,
    format: 'umd'
  }, {
    file: `./dist/anikyu.esm.js`,
    format: 'es'
  }],
  plugins: [
    resolve(),
    commonjs({
      extensions: ['.js'],
      ignoreGlobal: false,
      sourceMap: false,
    }),
    babel({
      exclude: 'node_modules/**',
      babelHelpers: 'runtime',
      "presets": [
        [
          "env",
          {
            "modules": false,
            "targets": {
              // The % refers to the global coverage of users from browserslist
              "browsers": [">0.25%", "not ie 11", "not op_mini all"]
            }
          }
        ]
      ],
      "plugins": [
        "@babel/plugin-external-helpers",
        [
          "@babel/plugin-transform-runtime",
          {
            corejs: 3
          }
        ]
      ]
    })
  ]
};

这一版中打出来的包里不包含polyfill,并且打包时提示了一些错误,之前查各种资料,一无所获:

今天居然成功解决!真的很意外,值得庆祝一下。