Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

使用Rollup构建你的JS代码 #20

Open
lihongxun945 opened this issue Jul 23, 2018 · 0 comments
Open

使用Rollup构建你的JS代码 #20

lihongxun945 opened this issue Jul 23, 2018 · 0 comments

Comments

@lihongxun945
Copy link
Owner

很多人知道 vue 等框架的JS代码是用 rollup 编译的,那么 rollup 是什么呢,它和 webpack 有什么异同?如果你也有这个疑惑,那么这篇文章正好可以解答。

Rollup 是什么

Rollup 本身(不包含任何插件的情况下)只是一个模块语法的转换工具,他可以把 ES6 的模块语法编译成不同的语法:

  • cjs 在node中使用的CMD语法
  • iife 直接在浏览器中运行
  • amd requirejs 的语法
  • umd 兼容 amdcmd

举个例子,我们有用 ES6 模块语法编写的代码如下:

foo.js

export default 'Hello world!'

main.js

import foo from './foo.js'

export default function () {
  console.log(foo)
}

显然ES6的模块语法无法在node中运行,我们使用rollup用这个命令进行打包:

rollup src/main.js -f cjs

打包出的结果如下:

'use strict';

var foo = 'Hello world!';

function main () {
  console.log(foo);
}

module.exports = main;

可以看到rollup做了两件事:

  • ES6 模块语法编译成了 node 的语法
  • 把两个文件的代码打包成了一份。

这就是Rollup本身做的所有事情,是不是很简单明了?

那么会有童鞋要问了,这也太简单了吧?如果我们需要编译 es6/7 中的其他语法呢?

如何处理 ES6/7 等新的JS语法

Rollup本身做的非常精简,任何除了上面讲到的功能外的其他功能,都需要插件来实现,比如我们要把 ES6 中的箭头函数编译一下,就需要安装额外的插件。

把前面的代码稍微改一下,假设我们有如下代码:

foo.js

export default () => {
  return 'Hello world!'
}

main.js

import foo from './foo.js'

export default function () {
  console.log(foo())
}

那么我们打包成 cjs 之后变成了这样:

'use strict';

var foo = () => {
  return 'Hello world!'
};

function main () {
  console.log(foo);
}

module.exports = main;

可以看到正如我们前面所说的,箭头函数根本不会被编译,因为 rollup 默认只会编译模块语法,其他语法他是不管的。为了编译 箭头函数等其他 es6/7 的语法,我们需要一个插件 rollup-plugin-babel

我们在 rollup.config.js 中进行如下配置(这里省略了.babelrc 的配置):

// rollup.config.js
import babel from 'rollup-plugin-babel'

export default {
  input: 'src/main.js',
  output: {
    file: 'bundle.js',
    format: 'cjs'
  },
  plugins: [
    babel()
  ]
}

那么打包出来的代码就变成这样了:

'use strict';

var foo = (function () {
  return 'Hello world!';
});

function main () {
  console.log(foo);
}

module.exports = main;

可以看到其中的箭头函数已经被转成了function

Tree shaking

我们在webpack源码解析 中提到过,webpack本身其实进行 tree-shaking 优化,他只负责把无用的exports删除,最终是由 uglify 完成的摇树优化。

我们都知道Webpack 的treeshaking其实是从 rollup 中 借鉴 来的,而rollup原生就实现了 tree shaking。如果我们把上面的代码稍微做一点修改,改成这样:

foo.js

export const foo = () => {
  return 'Hello world!'
}
export const bar = () => {
  return 'Hello world!'
}

main.js

import {foo} from './foo.js'

export default function () {
    console.log(foo())
}

可以看到其中的 bar 函数被直接删除了。

如何在我的项目中使用Rollup

Rollup 官方提供了两个示例项目 https://github.com/rollup/rollup-starter-apphttps://github.com/rollup/rollup-starter-lib。一个项目是开发JS框架,一个是我们正常的项目。

rollup-starter-lib 重点是展示如何把你的代码打包成不同的版本,以适应不同的环境。这个项目中打包成了三种模块语法: es, cjsumd
rollup-starter-app 重点是展示如何打包你的项目以在浏览器中运行。这个项目会把代码打包成 iife 模式,也就是把你的代码打包成一个自执行函数。另外还使用了 uglify 压缩代码,以及可以生成sourcemap

和 webpack 的区别

在Rollup官方提供的例子中我们就可以看出,Rollup(包括他的插件)做的仅仅是JS的编译打包工作,这和webpack是有本质区别的。webpack是一个通用的前端资源打包工具,它不仅处理JS,也可以通过loader来处理 CSS、图片、字体等各种前端资源,还提供了 hot reload 等方便前端项目开发的功能。如果不是开发一个JS框架,webpack显然会是一个更好的选择。

如果说相同点,Rollup和Webpack的核心都是处理JS,他们都会解析JS的语法树,然后分析模块依赖。如果对webpack的工作原理不了解,也可以参见我之前写的系列博客 webpack源码解析

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant