前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Rollup模块打包踩坑指南

Rollup模块打包踩坑指南

作者头像
luciozhang
发布2023-04-22 16:40:34
2.3K0
发布2023-04-22 16:40:34
举报
文章被收录于专栏:前端lucio前端lucio

Rollup是一个轻量级javascript模块打包器。相比于Webpack,Rollup更适合打包library。Rollup基于ES6模块,ES模块允许通过静态分析,实现tree-shaking优化,删除冗余代码。

对于Rollup和Webpack的选择,可以看下Rollup的官方文档:

Rollup 是用来构建库还是应用程序?(Is Rollup meant for building libraries or applications?) Rollup 已被许多主流的 JavaScript 库使用,也可用于构建绝大多数应用程序。但是 Rollup 还不支持一些特定的高级功能,尤其是用在构建一些应用程序的时候,特别是代码拆分和运行时态的动态导入 dynamic imports at runtime. 如果你的项目中更需要这些功能,那使用 Webpack可能更符合你的需求。

本文记录了打包一个js组件,并发布到npm的过程。

这次示例我们打包一个基于mobile-select封装的城市选择组件,先来看下将要被打包的代码。

代码语言:javascript
复制
import CityList from './list'
import MobileSelect from 'mobile-select'

const CitySelector = {}
CitySelector.districtData = null
CitySelector.instance = null
CitySelector.callback = null

/**
 * 初始化方法
 * @param trigger  省份城市控件id
 * @param title  标题
 * @param callback (indexArr, data) data是一个数组
 * @param type 类型 1 选择省市 2 选择省市区
 */
CitySelector.init = function (trigger, callback, title = "请选择省份城市", type = 1) {
    CitySelector.callback = callback

    CitySelector.districtData = CityList
    CitySelector.doInit(trigger, title, type)

}

// ***

export default CitySelector

可以看到,我们的代码import了两个外部库,list是存在本地的城市区划列表,mobile-select是一个开源的选择弹框组件。

1. 初始化项目

代码语言:javascript
复制
npm init

会生成一个package.json文件,修改下配置。

代码语言:javascript
复制
{
  "name": "tip-city-selector",
  "version": "1.0.5",
  "description": "cn city selection component",
  "main": "dist/tip-city-selector.js",
  "scripts": {
    "build": "rollup -c"
  },
  "author": "luciozhang",
  "license": "ISC",
  "devDependencies": {},
  "dependencies": {}
}

2. ESLint代码检查

通过代码规范,避免不必要的bug。

代码语言:javascript
复制
npm install --save-dev eslint

3. 安装Rollup

代码语言:javascript
复制
npm install --global rollup

4. 安装Babel相关插件

为了使用JavaScript的新特性。

https://www.rollupjs.com/guide/tools/#babel

关于babel的使用,推荐阅读下面这篇文章:

你真的会用 Babel 吗?

代码语言:javascript
复制
npm i -D rollup-plugin-babel

rollup-plugin-babel插件并不包含babel包,需要安装必要的babel包依赖。

代码语言:javascript
复制
npm i -D @babel/core @babel/preset-env

配置rollup.config.js

代码语言:javascript
复制
// rollup.config.js
import babel from 'rollup-plugin-babel';

export default {
  input: 'src/main.js',  //打包入口
  output: {
    file: 'bundle.js',  //输出文件
    format: 'cjs'       //模块化方式
  },
  plugins: [
    babel({
      exclude: 'node_modules/**' // 只编译我们的源代码,忽略第三方代码
    })
  ]
};

创建babel配置.babelrc

代码语言:javascript
复制
//.babelrc
{
  "presets": [
    ["latest", {
      "es2015": {
        "modules": false //设置"modules": false,否则 Babel 会在 Rollup 有机会做处理之前,将我们的模块转成 CommonJS,导致 Rollup 的一些处理失败
      }
    }]
  ],
  "plugins": ["external-helpers"] //允许 Rollup 在包的顶部只引用一次 “helpers”,而不是每个使用它们的模块中都引用一遍(这是默认行为)
}

安装插件babel-preset-latest和babel-plugin-external-helpers

代码语言:javascript
复制
npm i -D babel-preset-latest babel-plugin-external-helpers

运行一下,rollup -c。

报错了!

代码语言:javascript
复制
[!] (plugin babel) Error: /Users/luciozhang/tip-city-selector/src/main.js: Babel 7.0.0-beta.56 has dropped support for the 'helpersNamespace' utility.If you are using @babel/plugin-external-helpers you will need to use a newer version than the one you currently have installed. If you have your own implementation, you'll want to explore using 'helperGenerator' alongside 'file.availableHelper()'.

看了下rollup-plugin-babel的issues,原来Babel7.x版本不建议使用babel-plugin-external-helpers,也没对其进行支持。

对比了下英文文档,是中文文档翻译不及时的锅。

我们修改下.babelrc文件去掉babel-preset-latest babel-plugin-external-helpers两个插件。

代码语言:javascript
复制
//.babelrc
{
  "presets": [
    ["@babel/env", {"modules": false}]
  ]
}

5. Node 模块位置解析

再次运行rollup -c。

可以了!!

但发现一个WARN

代码语言:javascript
复制
(!) Missing global variable name
Use output.globals to specify browser global variable names corresponding to external modules
mobile-select (guessing 'MobileSelect')

我们已经安装了mobile-select模块,但没有被找到。

我们需要rollup-plugin-node-resolve 插件,来告知Rollup怎么查找外部模块,安装它

代码语言:javascript
复制
npm install -D rollup-plugin-node-resolve
代码语言:javascript
复制
//rollup.config.js
 plugins: [
       // …
    resolve({
       browser: true,
    }),
    // …
 ]

6. 加载 CommonJS 模块

再再次运行rollup -c。

WARN没了。但出现了一个Error。

代码语言:javascript
复制
[!] Error: 'default' is not exported by node_modules/mobile-select/mobile-select.js
https://rollupjs.org/guide/en/#error-name-is-not-exported-by-module

mobile-select模块是CommonJS模块,在Rollup中,加载CommonJS模块的能力放在可选插件中,我们需要安装rollup-plugin-commonjs。

代码语言:javascript
复制
npm install -D rollup-plugin-commonjs
代码语言:javascript
复制
//rollup.config.js
 plugins: [
       // …
    commonjs({
        include: ['node_modules/**']
    }),
    // …
 ]

7. PostCSS插件

再再再次运行rollup -c。

上一个Error解决了,我们来看下新的Error

代码语言:javascript
复制
!] Error: Unexpected token (Note that you need plugins to import files that are not JavaScript)
node_modules/mobile-select/mobile-select.css (1:0)

Rollup本身不支持加载css组件,我们需要安装一个Rollup的PostCSS插件。

代码语言:javascript
复制
npm install -D rollup-plugin-postcss
代码语言:javascript
复制
//rollup.config.js
 plugins: [
       // …
    postcss({
        extensions: ['.css'],
    }),
    // …
 ]

最后一次运行rollup -c,可以了。

8. 压缩代码

打包出来的js文件比较大,我们用rollup-plugin-terser压缩下代码。

代码语言:javascript
复制
npm install -D rollup-plugin-terser

在rollup.config.js的 插件列表加上terser()。

9. Rollup输出配置

打包的工作到这里就结束了,我们想要测试打包成果。

可能你还记得,我们打包输出的是CommonJS模块,因为rollup.config.js里面的output.format选项选择的是cjs。

可选的输出模块类型有下面这些:

  • amd – 异步模块定义,用于像 RequireJS 这样的模块加载器。
  • cjs – CommonJS,适用于 Node 和 Browserify/Webpack。
  • es – 将软件包保存为 ES 模块文件。
  • iife – 一个自动执行的功能,适合作为<script>标签。(如果要为应用程序创建一个捆绑包,您可能想要使用它,因为它会使文件大小变小。)
  • umd – 通用模块定义,以 amd,cjs 和 iife 为一体。

为了放在<script>中使用,方便测试,我们将打包格式改为umd。

同时,对于life和umd格式,我们需要指定输出模块名称,在js脚本中可以直接使用模块。

最终,我们的Rollup打包配置是这样的。

代码语言:javascript
复制
//rollup.config.js
import { terser } from 'rollup-plugin-terser';
import babel from 'rollup-plugin-babel';
import resolve from 'rollup-plugin-node-resolve';
import commonjs from 'rollup-plugin-commonjs'
import postcss from 'rollup-plugin-postcss';

export default {
    input: './src/main.js',
    output: {
        file: './dist/tip-city-selector.js',
        format: 'umd',
        name: 'CitySelector'
    },
    runtimeHelpers: false,
    plugins: [
        postcss({
            extensions: ['.css'],
        }),
        resolve({
            browser: true,
        }),
        commonjs({
            include: ['node_modules/**']
        }),
        babel({
            exclude: 'node_modules/**',
        }),
        terser(),
    ]
};

10. 发布npm

最后,如果对封装的组件有信心的话,我们可以把组件发布到npm

package.json的main属性指向包的出口,在我们的项目中,是"main": "dist/tip-city-selector.js"。

npm login登录,npm publish发布。

0. 参考文章

Rollup官方文档

你真的会用 Babel 吗?

rollup-plugin-babel

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-04-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 初始化项目
  • 2. ESLint代码检查
  • 3. 安装Rollup
  • 4. 安装Babel相关插件
  • 5. Node 模块位置解析
  • 6. 加载 CommonJS 模块
  • 7. PostCSS插件
  • 8. 压缩代码
  • 9. Rollup输出配置
  • 10. 发布npm
  • 0. 参考文章
相关产品与服务
腾讯云服务器利旧
云服务器(Cloud Virtual Machine,CVM)提供安全可靠的弹性计算服务。 您可以实时扩展或缩减计算资源,适应变化的业务需求,并只需按实际使用的资源计费。使用 CVM 可以极大降低您的软硬件采购成本,简化 IT 运维工作。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档