rollup打包ts+react最佳实践

2022-11-14 17:16:25 浏览数 (1)


导语

前段时间系统性学习了webpack,针对于打包项目,webpack的确非常强大,也非常合适,但是用来打包组件库,就显得比较的繁琐。相较而言,使用rollup打包组件库,就显得非常的简单容易,而本文也将介绍它的基础用法。

首先我们需要在全局安装rollup

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

命令行打包

rollup提供了开箱即用的打包能力,让我们在做一些基础打包操作的时候,无需配置config文件,直接使用命令行打包即可。

比如说,我们有一个index.js的文件

代码语言:javascript复制
export function add(a, b) {
  return a   b;
}

直接执行打包命令

代码语言:javascript复制
rollup index.js

就可以在控制台看到

当然,在控制台展示打包结果总是不那么方便,我们可以加上--file的参数,让它将内容打包进文件中

比如,我们想把方法打包进 bundle

代码语言:javascript复制
rollup main.js --file bundle.js

其他参数

除此之外,命令行打包还有很多参数可以配置

如果有多个入口脚本,就依次填写它们的文件名,并使用参数--dir指定输出目录。

代码语言:javascript复制
  $ rollup m1.js m2.js --dir dist

上面命令会在目录dist,打包生成多个文件:m1.js、m2.js、以及它们共同的依赖项(如果有的话)。

参数--format,会把打包结果放在一个自动执行函数(iife)里面。

代码语言:javascript复制
  $ rollup main.js --format iife

如果希望打包后代码最小化,使用参数--compact

代码语言:javascript复制
    $ rollup main.js --compact

更多配置戳链接:https://www.rollupjs.com/guide/command-line-reference

配置文件打包

除了命令行之外,rollup也会有它的一个配置文件,下面就简单介绍一下常用的一些配置项。

基础配置项

首先我们新建一个rollup.config.js文件,配置入口和出口

input 入口文件地址,当有多个入口文件时,是一个数组

代码语言:javascript复制
 input: './src/main.js'

output 打包结果配置

代码语言:javascript复制
output:{
  file:'bundle.js', // 输出文件
  format: 'cjs,  //  五种输出格式:amd /  es6 / iife / umd / cjs
  name:'A',  //当format为iife和umd时必须提供,将作为全局变量挂在window(浏览器环境)下:window.A=...
  sourcemap:true  //生成bundle.map.js文件,方便调试
}

配置完这个之后,我们的项目已经可以进行基础的打包了

package.json文件的scripts字段中新增指令

代码语言:javascript复制
scripts:{
   "build": "rollup --config",
}

执行npm run build就可以完成最基础的打包

支持commonjs

因为rollup使用的是es6的模块化,不支持CommonJS模块,自己写的时候可以尽量避免使用CommonJS模块的语法,但有些外部库的是cjs或者umd(由webpack打包的),所以使用这些外部库就需要支持CommonJS模块。

添加支持common.js的插件rollup-plugin-commonjs

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

在plugin中添加

代码语言:javascript复制
const commonjs = require('rollup-plugin-commonjs');
...
  plugins:[
    commonjs()
  ]
...

支持引用node_modules外部依赖

在 Rollup 中,我们要想使用 node_modules 里面的包,必须使用 @rollup/plugin-node-resolve 这个插件才行

这一点和 Webpack 很不一样,在 Webpack,我们可以无需任何配置,就能直接使用 node_modules 的包。

安装

代码语言:javascript复制
npm install -D @rollup/plugin-node-resolve

添加配置

代码语言:javascript复制
import resolve from '@rollup/plugin-node-resolve';

...
  plugins:[
    resolve()
  ]
...

支持加载css

一般情况下,我们写组件库是不会用到css的,但如果你编写的库需要引入css,就需要添加rollup-plugin-postcss插件,它支持css文件的加载、css加前缀、css压缩、对scss/less的支持等等。

安装

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

添加配置

代码语言:javascript复制
import postcss from 'rollup-plugin-postcss';

...
  plugins:[
    postcss()
  ]
...

这样配置仅支持引入css,如果想使用其他的功能,可以参考 https://www.npmjs.com/package/rollup-plugin-postcss

打包优化

rollup-plugin-delete

用来在每次打包前清理指定的目录或文件。

安装

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

添加配置

代码语言:javascript复制
const del = require('rollup-plugin-delete');
...
plugins:[
    del({ targets: 'dist/*',  verbose: true }),
]
...
rollup-plugin-terser

在生产环境中,代码压缩是必不可少的。我们使用rollup-plugin-terser进行代码压缩。

安装

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

添加配置

代码语言:javascript复制
import {terser} from 'rollup-plugin-terser';
...
plugins:[
    terser(),
]
...

需要rollup版本2.x

开启本地服务

和webpack一样,rollup也可以开启本地服务,方便我们在本地调试组件库等。

需要安装 rollup-plugin-serverollup-plugin-livereload

这两个插件常常一起使用,rollup-plugin-serve用于启动一个服务器,rollup-plugin-livereload用于文件变化时,实时刷新页面

安装

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

使用

代码语言:javascript复制
import {terser} from 'rollup-plugin-terser';
...
plugins:[
    serve({
        contentBase: '', //服务器启动的文件夹,默认是项目根目录,需要在该文件下创建index.html
        port: 8020, //端口号,默认10001
    }),
    livereload('dist'), //watch dist目录,当目录中的文件发生变化时,刷新页面
]

然后我们在package.json中加入新指令

代码语言:javascript复制
"scripts": {
    "dev": "rollup -wc"
},

启动npm run dev便能开启本地服务

支持es6

rollup打包出来的依赖默认是遵循es6语法,但是这样在有些地方不是很兼容,要编译的化,我们需要安装babel插件

需要rollup版本 < 3

安装

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

配置

代码语言:javascript复制
 plugins:[
    babel({
        exclude: 'node_modules/**'
    })
  ]

新增babelrc配置

代码语言:javascript复制
{
  "presets": [
    [
      "@babel/env",
      {
        "modules": false // 设置为false,否则babel会在rollup有机会执行其操作之前导致我们的模块转化为commonjs
      }
    ]
  ]
}

支持编译react

安装

代码语言:javascript复制
npm install -D @babel/preset-react

配置

代码语言:javascript复制
plugin:[
    ...
    babel({
      exclude: 'node_modules/**',
      extensions: ['.js', '.jsx'],
      presets: ['@babel/preset-env','@babel/preset-react'],
    }),
    ...
]

加载typescript

安装

代码语言:javascript复制
npm install @rollup/plugin-typescript typescript --save-dev 

配置

代码语言:javascript复制
plugin:[
    ...
    typescript(),
    ...
]

更多配置项参考 https://www.npmjs.com/package/@rollup/plugin-typescript

使用别名替换相对路径

安装@rollup/plugin-alias

代码语言:javascript复制
npm install @rollup/plugin-alias --save-dev

配置

代码语言:javascript复制
plugins:[
    ...
    alias({
      entries: [{ find: '@', replacement: resolveDir(' src ') }],
    }),
    ...
]

之后就可以像这样引入文件

代码语言:javascript复制
import * from '@/xxx/xxx';

配置外部引用

rollup默认会将我们用到的依赖项全部打包进bundle中,有的时候会造成我们的bundle特别的打大,我们可以通过配置exteral来将它们改为外部依赖,以此来减小我们的包体积

配置

代码语言:javascript复制
input:...
output:...
external:['react'] //告诉rollup不要将此react打包,而作为外部依赖,在使用该库时需要先安装相关依赖

至此,rollup打包的基础配置已经完成

完整配置

rollup.config.js

代码语言:javascript复制
import alias from '@rollup/plugin-alias';
import commonjs from 'rollup-plugin-commonjs';
import postcss from 'rollup-plugin-postcss';
import serve from 'rollup-plugin-serve';
import livereload from 'rollup-plugin-livereload';
import del from 'rollup-plugin-delete';
import babel from 'rollup-plugin-babel';
import typescript from '@rollup/plugin-typescript';
import { nodeResolve } from '@rollup/plugin-node-resolve';
import {terser} from 'rollup-plugin-terser';
const path = require('path');

export default {

  input: './src/main.js', //入口文件

  output: {
    file: './dist/bundle.js', //打包后的存放文件
    //dir: './dist', // 多入口打包必需加上的属性
    format: 'cjs', //输出格式 amd es6 iife umd cjs
    name: 'bundleName', //如果iife,umd需要指定一个全局变量
    sourcemap: true, // 是否开启代码回溯
  },

  plugins: [
    nodeResolve(), // 支持从node_modules引入其他的包
    commonjs(), //支持common.js
    // es6语法转义
    babel({
      exclude: 'node_modules/**',
      extensions: ['.js', '.jsx'],
      presets: ['@babel/preset-env', '@babel/preset-react'],
    }),

    postcss(), //支持加载css,添加前缀等

    typescript({
      exclude: 'node_modules/**',
      include: 'src/**',
    }),

    // 打包前清空目标目录
    del({ targets: 'dist/*', verbose: true }),
    
    // 压缩js
    terser(),
        
    serve({
      contentBase: '', //服务器启动的文件夹,默认是项目根目录,需要在该文件下创建index.html
      port: 8020, //端口号,默认10001
    }),
      
    livereload('dist'), //watch dist目录,当目录中的文件发生变化时,刷新页面
      
    // 使用别名
    alias({
      entries: [{ find: '@', replacement: path.join(__dirname, 'src') }],
    }),
  ],
  external:['react'] //告诉rollup不要将此lodash打包,而作为外部依赖,在使用该库时需要先安装相关依赖

};

package.json

代码语言:javascript复制
{
  "name": "rollup-test",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "type": "module",
  "scripts": {
    "test": "echo "Error: no test specified" &amp;&amp; exit 1",
    "build": "rollup --config",
    "dev": "rollup -wc"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/core": "^7.19.6",
    "@babel/preset-env": "^7.19.4",
    "@babel/preset-react": "^7.18.6",
    "@rollup/plugin-alias": "^4.0.2",
    "@rollup/plugin-node-resolve": "13.3",
    "@rollup/plugin-typescript": "^9.0.2",
    "lodash": "^4.17.21",
    "rollup": "2.42",
    "rollup-plugin-babel": "^4.4.0",
    "rollup-plugin-clear": "^2.0.7",
    "rollup-plugin-commonjs": "^10.1.0",
    "rollup-plugin-delete": "^2.0.0",
    "rollup-plugin-livereload": "^2.0.5",
    "rollup-plugin-postcss": "^4.0.2",
    "rollup-plugin-serve": "^2.0.1",
    "rollup-plugin-terser": "^7.0.2",
    "typescript": "^4.8.4"
  },
  "dependencies": {
    "react": "^18.2.0",
    "react-dom": "^18.2.0"
  }
}

项目链接

https://github.com/AdolescentJou/rollup-base-demo

最后

感谢你能看到这里,本文介绍了rollup的基础配置,以及一些常用的插件,希望对你有所帮助,之后会更新rollup的进阶文章,如果能留下你的一个赞,笔者将感激不尽。

参考链接

https://juejin.cn/post/7004297344300777502

https://juejin.cn/post/6844904058394771470

0 人点赞