Rollup 是我在重构 TNT.js 这个玩具框架时忽然发现的一个构建工具。因为需要升级整个 codebase 到 ES Modules ,所以一个好的构建工具十分重要。但是,这个项目之前用的“构建工具”就是把 TypeScript 编译成 JavaScript ,可变性并不强。在尝试使用 Webpack 的时候,我无论如何也没办法让编译产物通过 HTML 的 script
标签导入到页面中(这个项目是一个小前端框架,要能够在浏览器中运行,就必须使用 script
标签倒入,没有打包 HTML)。
然后在一位大佬的指引下,我发现了 Rollup.js ,原生支持 ESM ,感觉十分不错。于是,就诞生了这篇文章!
$ npm i -g rollup
跟 Webpack 一样,Rollup 也用一个独立的 JS 配置文件存放自己的运行设置。在 Rollup 里,配置文件的名字是 rollup.config.js
。
我在这个项目里使用的配置文件长这样:
import alias from "@rollup/plugin-alias";
import resolve from "@rollup/plugin-node-resolve";
import typescript from "@rollup/plugin-typescript";
import serve from "rollup-plugin-serve";
export default {
input: "src/index.ts",
preserveModules: true,
treeshake: false,
output: {
format: "esm",
sourcemap: true,
dir: "./dist",
name: "TNT"
},
plugins: [
alias({
entries: [
{ find: "runtime", replacement: "src/runtime" },
{ find: "plugins", replacement: "src/plugins" },
],
}),
resolve(),
typescript(),
serve(),
],
};
Rollup 也支持许多的插件,比如我这里用的 plugin-alias
,就是把 Webpack 里面的 alias
配置项移植了过来。这里需要注意,Rollup 原生并不支持 TypeScript ,需要单独安装 @rollup/plugin-typescript
插件才能使用。
我还是用了 plugin-node-resolve
,这个插件是用来解析导入 node_modules
中的模块的。最后的 rollup-plugin-serve
的作用就是在你运行 Rollup 时,自动启动一个开发服务器,提供预览。
在这里,我选用了 ESM 的打包方式,仅仅为了让我这个项目变得好玩点。output.dir
指定了输出目录。还需要注意的是,我关闭了摇树优化,因为我需要把所有的东西整体打包,而不是打包特定的部分。但是这带来的坏处就是需要手动检查导入,防止导入未使用的模块。
preserveModules
代表保留当前的所有模块,这样我就可以在构建后的代码中使用 import
语句了。
配置完了 Rollup 之后,可以用 rollup -c
来打包。当然,这样并不会热更新,你还需要指定 -w
参数来启动热更新。
至此,Rollup 已经完成了基本配置。但是,为了更好的开发体验,我还需要一个东西来热加载我的 HTML 文件 —— 但是并不是使用 Rollup(当然 Rollup 也支持导入 HTML ,只不过不符合我的需求)。
在 HTML 里导入 ESM 还是比较简单的。在 <script></script>
标签上加入 type="module"
就行啦。然后,就可以在 script
标签里面使用 import
语句了:
<script type="module">
import TNT from "./dist/src/runtime/TNT.js";
import { Value } from "./dist/src/plugins/tntjsapi-simp/ValueState.js";
import { Globals } from "./dist/src/runtime/GlobalEnvironment.js";
import { NumberType } from "./dist/src/runtime/SymbolTable.js";
import { PluginMain as TemplatePlugin } from "./dist/src/plugins/TemplateLanguage/PluginMain.js";
import { PluginMain as DebugPlugin } from "./dist/src/plugins/debug/PluginMain.js";
import { PluginMain as TNTScriptPlugin } from "./dist/src/plugins/tntscript/PluginMain.js";
window.onload = () => {
console.log(Globals.getAllPlugins())
const t = new TNT();
new Value("testValue", NumberType).setValue(23333)
console.log(Globals.symbolTable);
};
</script>
需要注意的是,你不需要提前使用 <script src="dist/xxx" />
来加载 ESM 文件。
但是,如果你现在打开配置好的 HTML 文件,会得到一个错误:
index.html:1
Access to script at 'file:///Volumes/Data/Develop/Nodejs/tntjs/dist/src/runtime/TNT.js' from origin 'null' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome-extension, edge, https, chrome-untrusted.
看来是直接使用文件协议传输不受 ESM 的支持。
解决方法就是启动一个热加载服务器来伺服我们的 HTML 文件。我选用了 live-server 包来解决这个问题。
首先,安装 live-server :
npm install -g live-server
然后,就可以在项目目录里直接运行 live-server
启动开发服务器啦!现在到 http://localhost:8080/ 去看看吧。
总的来说,Rollup 是一个非常好的构建工具,它可以让我们在编写代码的时候更加简单,省去繁琐的配置过程。但是,它的社区可能还不如 Webpack 成熟,所以目前来说 Webpack 可能略占上风。
最后放一下我一直提到的小项目的 GitHub 吧:https://github.com/Bug-Duck/tntjs/tree/dev
欢迎 star & fork !