因为在设计博客和 CMS 的时候,有一个设想就是在 CMS 里去编辑 md,同时实时预览,这个预览和实际提交在博客上展示要求完全一致。所以就想着自己弄一个预览模块,在两个项目之前共享代码。这就涉及到一个 Markdown Preview 的工具。这个工具其实就是从 MD => HTML,使用 highlight.js 做代码高亮,一些自定义的配置和样式文件,然后打包成一个 js 包。
这个打包环节其实是想用 webpack 打一个 umd 的包就得了,但是一直知道有个 rollup 的工具存在,非常轻量,同时 Vue.js 也是通过 rollup 打包的,所以就想做出一次尝试。以下是阅读文档,结合 awesome rollup 仓库总结的一些经验。
同时本文只会涉及到一些 rollup 相关的,关于 markdown 处理会再开一篇文章记录。
起步 package.json {
"name": "my-package",
"version": "0.1.0",
"main": "dist/my-package.js"
}
通常,包内的 package.json 通常用有一个叫 main 的属性,他说明的是本包的内容是在dist/my-package.js
中。
像 Webpack, Browserify 之类的 bundler 会解析这个 main, 然后引入 main 属性对应的 js,同时根据 dependencies 去载入相应依赖。 在第三方打包时一般都会优先选用 umd 的包,因为这样浏览器也可以使用,所以一般第三方的 lib 的 main 属性通常都是 umd 的包。
而 rollup 属于 ES2015-aware 的工具,在 rollup 内使用 CJS 或者 UMD 并不是最理想的情况,因为无法使用 ES6 module 的特性。 如果对方在使用 rollup 作为他的 bundler, 而也说了 rollup 属于 ES2015-aware 的工具,他会优先读取 package.json 里的 module 属性,如果没有,才会读 main 属性,这样既可以保证一般 bundler 可以正常解析文件,同时在使用 rollup 的时候会优先读取 module 里的 es 包。
所以 package.json 就会变成:
{
"name": "my-package",
"version": "0.1.0",
"main": "dist/my-package.umd.js",
"module": "dist/my-package.esm.js"
}
这对于打出的包来说属于双赢。 具体可以查看
官方对于这种做法的解释 配置文件 rollup 的配置文件可以使用 es6 语法编写 使用-c 来指定 config 文件,默认读取根目录下 rollup.config.js
rollup -c
rollup --config
rollup -c build/rollup.config.js
这里也放出我用的配置文件
import resolve from "@rollup/plugin-node-resolve";
import commonjs from "rollup-plugin-commonjs";
import pkg from "./package.json";
import dev from "rollup-plugin-dev";
import postcss from "rollup-plugin-postcss";
import { string } from "rollup-plugin-string";
import { terser } from "rollup-plugin-terser";
const devServerConfig = {
port: 3000,
};
const plugins = function (format) {
const commonPlugins = [
dev(devServerConfig),
postcss({
extract: false,
}),
string({
include: "**/*.md",
}),
terser(),
];
if (format === "umd") {
return [...commonPlugins, resolve(), commonjs()];
} else {
return commonPlugins;
}
};
export default [
// for browser
{
input: "src/index.js",
output: {
name: "MarkdownPreview",
file: pkg.browser,
format: "umd",
},
plugins: plugins("umd"),
},
// for cjs and esm
{
input: "src/index.js",
external: Object.keys(pkg.dependencies),
output: [
{ file: pkg.main, format: "cjs" },
{ file: pkg.module, format: "es" },
],
plugins: plugins(),
},
];
常用依赖 rollup-plugin-commonjs 支持解析 commonjs 包至 es6 module[@rollup/plugin-node-resolve](https://github.com/rollup/plugins/tree/master/packages/node-resolve) 支持解析 node_modules 里的包 之前的包rollup-plugin-node-resolve 已经 archive 了且不再维护 rollup-plugin-vue rollup-plugin-jsx rollup-plugin-md rollup-plugin-terser rollup-plugin-string 坑 rollup-plugin-uglify 因为之前没有用过terser 作为 minify 的工具,所以选择了 rollup-plugin-uglify 打包 esm 的时候竟然不支持 es6 语法。terser 官方也说了这个问题,Why choose terser? uglify-es is no longer maintained and uglify-js does not support ES6+. terser is a fork of uglify-es that mostly retains API and CLI compatibility with uglify-es and uglify-js@3.
所以使用 rollup-plugin-terser 作为 minify 工具。