前言
一般情况下,单一的中小型项目没有将自己模块化打包的必要。然而作为一个webgis开发在实际工作或者开源项目开发的场合下,往往会有需要将当前项目或者其中一部分功能性代码在其他项目中使用的场景。若仅仅简单的对代码的复制黏贴,会对代码的管理以及后续开发改进产生极大的不便,代码每有改动就需要在各个项目中保持同步更新,非常不便。此时对代码进行模块化打包是一个非常值得考虑的手段,模块化后的代码能非常便利的在其他项目中进行使用,并解决了代码内容变动产生的差异化问题。
Rollup是一个目前较为流行的JavaScript模块打包器。常见的JavaScript的开源程序及Library的模块化打包都是用到了Rollup。
搭建工程项目
1.新建工程
新建一个空文件夹,比如rollupDemo,执行项目初始化
npm init -y
2.安装rollup
安装rollup的依赖,在开发环境安装即可。
npm install rollup --save-dev
3.新建一个src存放组件内容,新建一个dist作为打包后的文件夹
- 在src中建一个components文件夹
- 新建一个name.js,导出name
const name = "gis";
export default name;
- 在src根目录下的创建main.js 使用name.js
import name from "./components/name";
console.log("hello" + name);
4.在根目录下新建一个rollup.config.js
export default {
// 核心选项
input: "./src/main.js", // 入口
output: {
// 出口 (如果要输出多个,可以是一个数组)
file: "./dist/bundle.js", //出口文件
format: "cjs", // 生成包的格式 //amd //cjs //es //iife //system //umd
},
};
5.在package.json添加scripts命令与type类型
"type": "module",
"scripts": {
"build": "rollup -c"
}
-c, --config 使用配置文件(如果使用参数但是值没有指定, 默认就是 rollup.config.js)
-m, --sourcemap 生成 sourcemap (-m inline
生成行内 map)
-w, --watch 监听 bundle 中的文件并在文件改变时重新构建
如果有多个打包配置,可通过下面的写法添加不同的命令读取对应的配置文件
"devjs": "rollup -w -m -c ./build/rollup.config.dev.js",
6.执行编译查看结果
npm run dev
插件的使用
1.使用Babel
上面打包出来的语法还是es6,为了正确解析我们的模块并使其与旧版浏览器兼容,我们应该包括babel来编译输出es5这个看使用场景可用可不用。
1.1安装依赖
npm install @rollup/plugin-babel @babel/core @babel/preset-env --save-dev
1.2 配置rollup.config.js
import babel from "@rollup/plugin-babel"; //引用依赖
export default {
// 核心选项
input: "./src/main.js", // 入口
output: {
// 出口 (如果要输出多个,可以是一个数组)
file: "./dist/bundle.js", //出口文件
format: "cjs", // 生成包的格式
},
plugins: [
babel({
exclude: "node_modules/**", //依赖文件不编译
}),
],
};
1.3 在src下建立 .babelrc
{
"presets": [
[
"@babel/preset-env",
{
"modules": false // 设置为false,否则babel会在rollup有机会执行其操作之前导致我们的模块转化为commonjs
}
]
]
}
1.4 编译结果对比 const 变成了var
首先,我们设置 “modules”: false ,否则 Babel 会在 Rollup 有机会做处理之前,将我们的模块转成 CommonJS ,导致 Rollup 的一些处理失败。
2.第三方依赖的使用
在某些时候,您的项目可能使用从NPM安装到node_modules文件夹中的依赖文件。
2.1.安装一个第三方依赖测试下
npm install lodash --save-dev
2.2.在main.js添加代码引用
import name from "./components/name";
import _ from "lodash";
const arr = _.concat([1, 2], 3, 4, [5]);
console.log(arr);
console.log("hello" + name);
2.3.安装插件
npm install @rollup/plugin-node-resolve @rollup/plugin-commonjs --save-dev
2.4.配置rollup.config.js文件
我将forma变更成es,你们可以根据需求自行选择
import babel from "@rollup/plugin-babel";
import resolve from "@rollup/plugin-node-resolve"; //插件允许我们加载第三方模块
import commonjs from "@rollup/plugin-commonjs";
export default {
// 核心选项
input: "./src/main.js", // 入口
output: {
// 出口 (如果要输出多个,可以是一个数组)
file: "./dist/bundle.js", //出口文件
format: "es", // 生成包的格式
},
plugins: [
resolve(), //将依赖一起打包进去
commonjs(),
babel({
exclude: "node_modules/**", //依赖文件不编译
}),
],
//external: ["lodash"],
};
external 配置不被打包的依赖
最后一行注释后打包效果如下:
打包完500kb,将三方依赖一起打包进来了。如果不想这样可添加external过滤不想打包的文件
external: ["lodash"]
结果如下:
import _ from 'lodash';
/*
* @Author: ysh
*/
var name = "gis";
/*
* @Author: ysh
*/
var arr = _.concat([1, 2], 3, 4, [5]);
console.log(arr);
console.log("hello" + name);
3.编译ts
3.1添加Giser.ts文件(components文件夹下)
Giser.ts
class Giser {
giser: string;
constructor(message: string) {
this.giser = message;
}
read() {
console.log("arcgis");
}
}
export default Giser;
main.js
import name from "./components/name";
import _ from "lodash";
import Giser from "./components/Giser";
const a = new Giser("a");
a.read();
const arr = _.concat([1, 2], 3, 4, [5]);
console.log(arr);
console.log("hello" + name);
3.2安装插件
npm install @rollup/plugin-typescript --save-dev
npm install tslib typescript --save-dev
3.3配置rollup.config.js
在这里插入代码片
3.4 配置tsconfig.json (根目录添加tsconfig.json文件)
{
"compilerOptions": {
"lib": ["es6"],
"module": "ESNext",
"allowJs": true
},
"exclude": ["node_modules"],
"include": ["src/**/*"]
}
3.5编译结果
4.压缩代码
去除注释与混淆变量去除空格
4.1安装插件
npm install rollup-plugin-terser --save-dev
4.2.配置rollup.config.js文件
import babel from "@rollup/plugin-babel";
import resolve from "@rollup/plugin-node-resolve"; //插件允许我们加载第三方模块
import commonjs from "@rollup/plugin-commonjs";
import { terser } from "rollup-plugin-terser"; //压缩代码
export default {
// 核心选项
input: "./src/main.js", // 入口
output: {
// 出口 (如果要输出多个,可以是一个数组)
file: "./dist/bundle.js", //出口文件
format: "es", // 生成包的格式
},
plugins: [
resolve(), //将依赖一起打包进去
commonjs(),
babel({
exclude: "node_modules/**", //依赖文件不编译
}),
terser(), //压缩代码
],
external: ["lodash"],
};
4.3打包结果
import o from"lodash";var l=o.concat([1,2],3,4,[5]);console.log(l),console.log("hellogis");
5.编译css
5.1 安装插件
npm install rollup-plugin-postcss --save-dev
5.2 创建css文件,然后在main.js里引用
import "./style.css";
5.3 配置rollup.config.js文件
import babel from "@rollup/plugin-babel";
import resolve from "@rollup/plugin-node-resolve"; //插件允许我们加载第三方模块
import commonjs from "@rollup/plugin-commonjs";
// import { terser } from "rollup-plugin-terser"; //压缩代码
import typescript from "@rollup/plugin-typescript";
import postcss from "rollup-plugin-postcss";
export default {
// 核心选项
input: "./src/main.js", // 入口
output: {
// 出口 (如果要输出多个,可以是一个数组)
file: "./dist/bundle.js", //出口文件
format: "es", // 生成包的格式
},
plugins: [
typescript(),
resolve(), //将依赖一起打包进去
commonjs(),
babel({
exclude: "node_modules/**", //依赖文件不编译
}),
// terser(), //压缩代码
postcss({
plugins: [],
}),
],
external: ["lodash"],
};
5.4 编译
编译出现报错
Error: Cannot find module 'postcss'
我发现是"rollup-plugin-postcss": “^4.0.2”,的版本太高了,我将4.0.2改成3.0.2重新安装
然后重新打包,css成功打包
var css_248z = "body {\r\n background-color: red;\r\n display: flex;\r\n}\r\n";
styleInject(css_248z);
6.开启本地服务器
在实际开发过程中,我们肯定要运行代码,查看页面,这时有个本地服务器就很重要,这样可以调试代码。
6.1 安装插件
npm install rollup-plugin-serve --save-dev
npm install rollup-plugin-livereload --save-dev
npm install @rollup/plugin-html --save-dev
rollup-plugin-livereload 热更新 可不要
@rollup/plugin-html 为自动生成html使用可不要
6.2 配置rollup.config.js
import babel from "@rollup/plugin-babel";
import resolve from "@rollup/plugin-node-resolve"; //插件允许我们加载第三方模块
import commonjs from "@rollup/plugin-commonjs";
import { terser } from "rollup-plugin-terser"; //压缩代码
import typescript from "@rollup/plugin-typescript";
import postcss from "rollup-plugin-postcss";
import serve from "rollup-plugin-serve";
import livereload from "rollup-plugin-livereload";
import html from "@rollup/plugin-html";
const makeHtmlAttributes = (attributes) => {
if (!attributes) {
return "";
}
const keys = Object.keys(attributes);
// eslint-disable-next-line no-param-reassign
return keys.reduce(
(result, key) => (result += ` ${key}="${attributes[key]}"`),
""
);
};
export default {
// 核心选项
input: "./src/main.js", // 入口
output: {
// 出口 (如果要输出多个,可以是一个数组)
file: "./dist/bundle.js", //出口文件
format: "es", // 生成包的格式
},
plugins: [
typescript(),
resolve(), //将依赖一起打包进去
commonjs(),
babel({
exclude: "node_modules/**", //依赖文件不编译
}),
terser(), //压缩代码
postcss({
plugins: [],
}),
serve({
// open: true,
contentBase: "dist",
}),
// copy默认的html文件,不想手动导入index.js
html({
fileName: "index.html",
title: "测试rollup开发环境",
template: async ({ attributes, files, meta, publicPath, title }) => {
// 解析script
const scripts = (files.js || [])
.map(({ fileName }) => {
const attrs = makeHtmlAttributes(attributes.script);
return `<script src="${publicPath}${fileName}"${attrs}></script>`;
})
.join("\n");
// 解析css
const links = (files.css || [])
.map(({ fileName }) => {
const attrs = makeHtmlAttributes(attributes.link);
return `<link href="${publicPath}${fileName}" rel="stylesheet"${attrs}>`;
})
.join("\n");
// 解析mata data
const metas = meta
.map((input) => {
const attrs = makeHtmlAttributes(input);
return `<meta${attrs}>`;
})
.join("\n");
return `
<!doctype html>
<html${makeHtmlAttributes(attributes.html)}>
<head>
${metas}
<title>${title}</title>
${links}
</head>
<body>
<div id='app'>APP 页面</div>
${scripts}
</body>
</html>`;
},
}),
livereload(),
],
external: ["lodash"],
};
打包结果,在浏览器打开这个网址,发现除lodash均加载正常,请根据自己的应用场景选中输出类型和引用与拷贝不打包的js至dist中,并修改配置文件中的html.
7.区分开发环境和生产环境
在开发环境我们需要sourcemap开启,配置热更新和本地服务,在生产环境我们需要sourcemap关闭,不需要热更新和本地服务,需要代码压缩等,所以需要区分。
将rollup.config.js拆分成两个rollup.config.dev.js和rollup.config.build.js,再结合我们项目实际情况来编写配置文件。