rollup 是一个 JavaScript 模块打包器,在功能上要完成的事和webpack性质一样,就是将小块代码编译成大块复杂的代码,例如 library 或应用程序。在平时开发应用程序时,我们基本上选择用webpack,相比之下,rollup.js更多是用于library打包,我们熟悉的vue、react、vuex、vue-router等都是用rollup进行打包的。
rollup安装与使用
首先是安装:
npm i rollup -g # 全局安装
npm i rollup -D # 项目本地安装
复制代码
打包一个js文件
如下新建一个项目,并安装rollup,创建两个文件:hello.js和index.js
如果是全局安装,直接在项目根目录下执行:
rollup -i src/index.js -o dist/bundle.js -f es
**
如果是项目本地安装,在package.json的script字段中添加:
"dev": "rollup -i src/index.js -o dist/bundle.js -f es"
,然后执行npm run dev
在这里,我们以本地安装为例。如下,rollup在命令行输出了打包结果。
在这段指令中:
-
-i
指定要打包的文件,-i
是--input
的缩写。 -
src/index.js
是-i
的参数,即打包入口文件。 -
-o
指定输出的文件,是--output.file
或--file
的缩写。(如果没有这个参数,则直接输出到控制台) -
dist/bundle.js
是-o
的参数,即输出文件。 -
-f
指定打包文件的格式,-f
是--format
的缩写。 -
es
是-f
的参数,表示打包文件使用ES6模块规范。
rollup支持的打包文件的格式有amd, cjs, es\esm, iife, umd。其中,amd为AMD标准,cjs为CommonJS标准,esm\es为ES模块标准,iife为立即调用函数, umd同时支持amd、cjs和iife。
rollup配置文件
在项目开发中,我们通常会使用配置文件,这不仅可以简化命令行操作,同时还能启用rollup的高级特性。
在项目根目录下创建rollup.config.js
。
export default {
input: "./src/index.js",
output: [
{
file: './dist/my-lib-umd.js',
format: 'umd',
name: 'myLib'
//当入口文件有export时,'umd'格式必须指定name
//这样,在通过<script>标签引入时,才能通过name访问到export的内容。
},
{
file: './dist/my-lib-es.js',
format: 'es'
},
{
file: './dist/my-lib-cjs.js',
format: 'cjs'
}
]
}
复制代码
使用Rollup的配置文件,可以使用rollup --config
或者rollup -c
指令。
//修改package.json的script字段
"dev": "rollup -c" // 默认使用rollup.config.js
"dev": "rollup -c my.config.js" //使用自定义的配置文件,my.config.js
复制代码
src/index.js
内容:
import { hello } from './hello'
hello()
export const world = 'world'
复制代码
打包后的文件: 可以看出,同样的入口文件,es格式的文件体积最小。
rollup插件
上面我们知道了rollup的基础用法,在实际应用中,会有很多更复杂的需求,比如,怎样支持es6语法,怎样打包.vue文件,怎样压缩我们js的代码等等。在rollup中,我们借助插件来完成。
在webpack中,使用loader对源文件进行预处理,plugin完成构建打包的特定功能需求。rollup的plugin兼具webpack中loader和plugin的功能。
一些常用的插件。
rollup-plugin-babel
rollup-plugin-babel
用于转换es6语法。
将src/hello.js
中的内容改写成:
export const hello = () => {
console.log('hello world')
}
复制代码
在未使用babel插件的情况下,打包结果:
使用babel插件:
npm i rollup-plugin-babel @babel/core @babel/preset-env --D
//rollup.dev.js
import babel from 'rollup-plugin-babel'
export default {
input: ...,
output: ...,
plugins:[
babel({
exclude: 'node_modules/**'
})
]
}
复制代码
在项目根目录创建.babelrc
文件。
{
"presets": [
[
"@babel/preset-env"
]
]
}
复制代码
再次打包:
rollup-plugin-commonjs
rollup默认是不支持CommonJS模块的,自己写的时候可以尽量避免使用CommonJS模块的语法,但有些外部库的是cjs或者umd(由webpack打包的),所以使用这些外部库就需要支持CommonJS模块。
新建一个src/util.js
文件,内容如下:
module.exports = {
a: 1
}
复制代码
在src/index.js
中引入util.js
import util from './util'
console.log(util.a)
复制代码
npm run dev
打包会报错:
这就需要使用rollup-plugin-commonjs
,首先,npm i rollup-plugin-commonjs --D
.
在rollup.config,js
中加入:
import commonjs from 'rollup-plugin-commonjs'
export default {
input: ...,
output: ...,
plugins:[
commonjs()
]
}
复制代码
再npm run dev
打包,没有报错。
我们还可以在代码使用require引入模块:
// src/index.js
const util = require('./util')
console.log(util.a)
复制代码
rollup-plugin-commonjs
可以识别require语法,并打包成es模块语法,打包的出的my-lib-es.js的内容如下:
var util = {
a: 1
};
console.log(util.a);
var src = {
};
export default src;
复制代码
rollup-plugin-postcss
处理css需要用到的插件是rollup-plugin-postcss
。它支持css文件的加载、css加前缀、css压缩、对scss/less的支持等等。
首先,安装,npm i rollup-plugin-postcss postcss --D
,然后在rollup.config.js
中配置:
import postcss from 'rollup-plugin-postcss'
export default {
input: ...,
output: ...,
plugins:[
postcss()
]
}
复制代码
然后,新建一个test.css,在index.js中引入。 打包后得到的umd文件:
(function (factory) {
typeof define === 'function' && define.amd ? define(factory) :
factory();
}((function () { 'use strict';
function styleInject(css, ref) {
if ( ref === void 0 ) ref = {};
var insertAt = ref.insertAt;
if (!css || typeof document === 'undefined') { return; }
var head = document.head || document.getElementsByTagName('head')[0];
var style = document.createElement('style');
style.type = 'text/css';
if (insertAt === 'top') {
if (head.firstChild) {
head.insertBefore(style, head.firstChild);
} else {
head.appendChild(style);
}
} else {
head.appendChild(style);
}
if (style.styleSheet) {
style.styleSheet.cssText = css;
} else {
style.appendChild(document.createTextNode(css));
}
}
var css_248z = "body{\r\n color: green;\r\n}";
styleInject(css_248z);
})));
复制代码
导入的css文件将用于生成style标签,插入到head中。
我们新建一个测试文件,引入该umd文件。可以看到head中有我们在test.css
写入的内容。
<body>
test css
</body>
<script src="../dist/my-lib-umd.js"></script>
复制代码
css加前缀
借助autoprefixer
插件来给css3的一些属性加前缀。安装npm i autoprefixer@8.0.0 --D
,配置:
import postcss from 'rollup-plugin-postcss'
import autoprefixer from 'autoprefixer'
export default {
input: ...,
output: ...,
plugins:[
postcss({
plugins: [
autoprefixer()
]
})
]
}
复制代码
使用autoprefixer
除了以上配置,还需要配置browserslist,有2种方式,一种是建立.browserslistrc文件,另一种是直接在package.json里面配置,我们在package.json中,添加"browserslist"字段。
"browserslist": [
"defaults",
"not ie < 8",
"last 2 versions",
"> 1%",
"iOS 7",
"last 3 iOS versions"
]
复制代码
修改test.css
的内容:
body{
color: green;
display: flex;
}
复制代码
打包,刷新刚才的测试页面。
css压缩
cssnano对打包后的css进行压缩。使用方式也很简单,和autoprefixer一样,安装cssnano
,然后配置。
plugins:[
postcss({
plugins: [
autoprefixer(),
cssnano()
]
})
]
复制代码
抽离单独的css文件
rollup-plugin-postcss
可配置是否将css单独分离,默认没有extract
,css样式生成style
标签内联到head中,配置了extract
,就会将css抽离成单独的文件。
postcss({
plugins: [
autoprefixer(),
cssnano()
],
extract: 'css/index.css'
})
复制代码
当然,在页面也需要单独引入打包好的css文件。
支持scss/less
实际项目中我们不太可能直接写css,而是用scss或less等预编译器。rollup-plugin-postcss
默认集成了对scss、less、stylus的支持,在我们项目中,只要配置了rollup-plugin-postcss
,就可以直接使用这些css预编译器,很方便的。
rollup-plugin-vue
rollup-plugin-vue用于处理.vue文件。vue2和vue3项目所用的rollup-plugin-vue版本不一样,vue的编译器也不一样。
- vue2:
rollup-plugin-vue^5.1.9
+vue-template-compiler
- vue3:
rollup-plugin-vue^6.0.0
+@vue/compiler-sfc
以vue2为例:
npm i rollup-plugin-vue@5.1.9 vue-template-compiler --D
在rollup.dev.js
中加入rollup-plugin-vue
import vue from 'rollup-plugin-vue'
export default {
...
plugins:[
vue()
]
}
复制代码
新建一个vue文件,并修改src/index.js
npm run dev
打包,我们来看看生成的umd
文件。
测试umd文件:
<body>
<div id="app">
<hello></hello>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="../dist/my-lib-umd.js"></script>
<script>
Vue.use(myLib)
new Vue({
el: '#app'
})
</script>
复制代码
组件使用成功,说明我们的配置可以编译、打包.vue文件了。
rollup-plugin-vue
也是默认支持scss、less、stylus,可以在项目中直接使用。给.vue文件中的css自动加前缀,需要在rollup-plugin-vue
中配置。更多配置参考rollup-plugin-vue
import vue from 'rollup-plugin-vue'
import autoprefixer from 'autoprefixer' //同样要配置browserslist
import cssnano from 'cssnano'
export default {
...
plugins:[
vue({
style: {
postcssPlugins: [
autoprefixer(),
cssnano()
]
}
})
]
}
复制代码
rollup-plugin-terser
在生产环境中,代码压缩是必不可少的。我们使用rollup-plugin-terser
进行代码压缩。
import { terser } from 'rollup-plugin-terser'
export default {
...
plugins:[
terser()
]
}
复制代码
在上面的过程中,我们都是打包好文件,然后通过script引入,或npm link然后在别的项目中调试,这更像是组件库的调试方法。如果我们用rollup打包一个应用,它能否像webpack那样热更新呢?答案是可以的。我们需要借助rollup-plugin-serve
和rollup-plugin-livereload
。
rollup-plugin-serve、rollup-plugin-livereload
这两个插件常常一起使用,rollup-plugin-serve
用于启动一个服务器,rollup-plugin-livereload
用于文件变化时,实时刷新页面。
import serve from 'rollup-plugin-serve'
import livereload from 'rollup-plugin-livereload'
export default {
...
plugins:[
serve({
contentBase: '', //服务器启动的文件夹,默认是项目根目录,需要在该文件下创建index.html
port: 8020 //端口号,默认10001
}),
livereload('dist') //watch dist目录,当目录中的文件发生变化时,刷新页面
]
}
复制代码
我们需要在index.html手动加入打包后的文件,js或者css,因为此时并没有自动注入。然后访问http://localhost:8020
就可以看到index.html中的内容。
然而,此时修改src中的文件,页面并不会实时刷新,因为dist目录下的文件并没有更新。 rollup监听源文件的改动很简单,就是在执行打包命令时,添加 -w
或者 --watch
//package.json
"scripts": {
"dev": "rollup -wc"
},
复制代码
大功告成,再修改源文件的代码,你就会发现浏览器实时更新了。
打包按需加载的组件库
都到这里了,打包按需加载组件就太简单了。
对于组件库项目,支持按需加载需要满足:组件库以ES模块化方式导出。 而rollup本来就支持ES模块的导出。
新建两个vue组件,hello和test:
修改src/index.js
:
import Hello from "./components/Hello"
import Test from "./components/Test"
function install(Vue){
Vue.use(Hello)
Vue.use(Test)
}
/***
在es模块中, 能被按需引入的变量需要用这些方式导出:
export const a = 1
export function a(){}
export { a, b }
而不能使用export default
***/
export {
Hello,
Test
}
export default install //umd
复制代码
修改rollup.config.js
如下:
import babel from 'rollup-plugin-babel'
import commonjs from 'rollup-plugin-commonjs'
import vue from 'rollup-plugin-vue'
import autoprefixer from 'autoprefixer'
export default {
input: "./src/index.js",
output: [
{
file: './dist/my-lib-umd.js',
format: 'umd',
name: 'myLib'
},
{
file: './dist/my-lib-es.js',
format: 'es'
},
{
file: './dist/my-lib-cjs.js',
format: 'cjs'
}
],
plugins:[
babel({
exclude: 'node_modules/**'
}),
vue({
style: {
postcssPlugins: [
autoprefixer()
]
}
}),
commonjs()
],
external:[ //外部库, 使用'umd'文件时需要先引入这个外部库
'vue'
]
}
复制代码
打包后,修改package.json:
"main": "dist/my-lib-cjs.js",
"module": "dist/my-lib-es.js",
复制代码
然后就可以在测试项目中进行测试了。具体可以参考怎样在本地调试组件库
import { Hello } from "my-lib-new"
Vue.use(Hello)
复制代码
至此,我们用rollup打包按需加载的组件库就完成了,整体感觉,要比webpack方便很多,按需加载组件的时候也不需要借助插件,在类库打包方面是挺优秀的了。
作者:Alaso
链接:https://juejin.cn/post/6934698510436859912
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。