rollup是面向library的?!

写在前面


Rollup was designed with libraries rather than apps in mind, and it is a perfect fit for React’s use case.

在Behind the Scenes: Improving the Repository Infrastructure – React Blog看到了这个,有些惊讶,这样好的东西,为什么只是面向类库呢?什么原因致使它不适合用来构建App?

零.webpack

rollup是面向library的?!

webpack致力于复杂SPA的模块化构建,非常吸引人的是各种loader:


Essentially, webpack loaders transform all types of files into modules that can be included in your application’s dependency graph.

以一致的方式处理各种资源依赖,通过loader屏蔽掉了资源类型差异(js是module,css是module,img也是module……),优势如下:


No more carefully placing your files in the right folders and hacked-together scripts for adding hashes to file URLs — webpack can take care of it for you.

另一些非常强大的特性包括:

Code Splitting:生产环境按需加载/并行加载

Tree Shaking:构建时去掉无用代码(export)

HMR:开发中模块热替换

Commons Chunk:构建时提取公共依赖

Dependency Graph:构建完毕输出模块依赖图,让bundle有了可读性

一.初衷
rollup一开始就是面向ES6 module的:


Next-generation ES6 module bundler.

当时AMD、CMD、UMD的格式之争还很火热,ES6 module还没有浏览器实现。rollup就这样冒了出来


Rollup was created for a different reason: to build flat distributables of JavaScript libraries as efficiently as possible, taking advantage of the ingenious design of ES2015 modules.

(引自Webpack and Rollup: the same but different,rollup作者亲述)

希望充分利用ES6 module机制,构建出结构扁平,性能出众的类库bundle,即面向library设计的

二.核心优势


It solves one problem well: how to combine multiple modules into a flat file with minimal junk code in between.

rollup让人惊艳的是其bundle的干净程度,尤其是iife格式,内容非常干净,没什么多余代码,真的只是把各模块按依赖顺序,先后拼接起来了

这与rollup的模块处理思路有关:


To achieve this, instead of turning modules into functions like many other bundlers, it puts all the code in the same scope, and renames variables so that they don’t conflict. This produces code that is easier for the JavaScript engine to parse, for a human to read, and for a minifier to optimize.

把所有模块都扁平地放在bundle文件内最外层作用域中,模块之间没有作用域隔离,依靠重命名来解决同一作用域下命名冲突的问题。几个显而易见的好处:

运行时性能(代码结构扁平,便于解析)

bundle源码可读性(自然的顺序结构,没有模块定义/跳转)

压缩可优化性(没有模块定义之类的压缩不掉的样板代码)

这样做的缺点也很明显:

模块系统过于静态化,HMR之类的特性很难实现

仅面向ES6 module,无法可靠地处理cjs,umd依赖(每次用rollup-plugin-commonjs都会遇到问题)

如果只是面向lib的话,第一点不支持也不要紧,但第二点着实头疼,二级依赖是不可控的,总是不可避免地会遇到cjs模块无法转自动换到ES6 module的一些问题,例如:


‘foo’ is not exported by bar.js (imported by baz.js)

一些场景可以按照Troubleshooting通过namedExports的方式不太愉快地解决,另一些时候通过external或globals绕过去,甚至还有需要调整plugin应用顺序的解法……但没有办法彻底解决这类问题:


Webpack gets around the need for namedExports by keeping everything as CommonJS modules and implementing Node’s require system in the browser, which is why the resulting bundles are larger and take longer to start up. Both options are valid, but that’s the tradeoff to be aware of — more config (Rollup, when using modules like React), or larger bundles (webpack).

(引自Is “named exports” feature or bug?)

虽然cjs终将成为历史,但目前以及眼下,npm仍然存在相当多的cjs模块,无论是SPA还是library,仍然面经常临处理cjs模块依赖的问题

三.选用原则
Use webpack for apps, and Rollup for libraries

构建App的话,webpack比较合适,如果是类库,当然rollup更好

webpack构建App的优势体现在以下几方面:

强大的插件生态,主流前端框架都有对应的loader

面向App的特性支持,比如之前提到的HMR,Code Splitting,Commons Chunk等都是开发App必要的特性

简化Web开发各个环节,包括图片自动base64,资源缓存(chunkId),按路由做代码拆分,懒加载等,都不难实现

可靠的依赖模块处理,不像rollup面临cjs的问题,__webpack_require__没这些烦恼

而rollup没有这些优势,做代码拆分等会遇到一些不太容易解决的问题,没有足够的时间和把握的话,不要轻易尝试把rollup作为App构建工具

rollup的优势在于高效率的bundle,这正是类库所追求的,即便费一点周折(正如React 16所做的),为了性能也是值得的

注意,这个原则只是说用合适的工具做合适的事情,适用于多数一般场景,用rollup构建App,用webpack构建类库的也很常见:


That’s not a hard and fast rule — lots of sites and apps are built with Rollup, and lots of libraries are built with webpack. But it’s a good rule of thumb.

典型的,如果业务本身没太多第三方模块依赖,并且风格约定遵循ES6 module,用rollup构建App也很合适(Code Splitting等也不是完全做不到)

P.S.另外,rollup也不太容易像glup或webpack一样进行基于stream的扩展,比如从一个vue文件中分离出三部分分别处理(vue插件好像还不支持ts)

四.外部依赖

对于React之类的类库,应该尽可能地作为第三方依赖独立出去,而不是build进bundle,几个原因:

性能会变差,比如React 16费了好大劲切换到了rollup + GCC(Google Closure Compiler)达到了109kb,自己编一次立马回到解放前

不利于缓存,类库不经常更新,可以当做静态资源充分发挥缓存优势,而手动build的内容受工具配置影响

rollup下可以通过external + globals配置来标记外部依赖:


external: ['react', 'react-dom'],
output: {
  globals: {
    'react': 'React',
    'react-dom': 'ReactDOM'
  }
}

这样生成的bundle为:


// iife
(function (React,ReactDOM) {
    //...
}(React,ReactDOM));

// cjs
var React = _interopDefault(require('react'));
var ReactDOM = _interopDefault(require('react-dom'));

所以一般把业务代码打包成iife,再通过script引用CDN第三方类库:


<script crossorigin src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
<!-- 或者聚合的版本 -->
<script crossorigin src="//cdn.jsdelivr.net/combine/npm/react@16.0.0/umd/react.production.min.js,npm/react-dom@16.0.0/umd/react-dom.production.min.js"></script>

P.S.rollup的external与globals有些奇怪,无论是key还是value,还是这两个东西竟然要配合使用,更多信息请查看[question] Difference between externals and globals

参考资料

Webpack and Rollup: the same but different:很有意思的文章,发现得太晚了

Handling 3rd-party JavaScript with Rollup

原文地址:https://blog.51cto.com/15080030/2592709

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


一准备工作umi为react的一个封装比较nice的脚手架。优点当然就是安装方便,开箱即用,集成了诸多好用功能,详见官网。当然缺点就是无法暴露原始的webpack.config.json文件,只能按照官方文档上特定的方法进行修改,而文档却并不完善。项目顺利进行大家笑嘻嘻,一旦遇到偏难怪需求,
webpack在引入两个依赖的包时,可能需要使用shimming,意思是处理代码上的兼容1、在main.js中引入jqueryimport$from'jquery'importappendfrom'./append'//下面的给页面添加元素文件append()2、append.js使用main.js的$向页面中添加元素functionappDomFunc(){
  Happypack (plugin)多线程使用loader编译文件treeshaking删除无用JS代码,依赖ESM规范source-map生产环境一定去掉process.env.XXX配置环境变量,区分各种编译环境splitchunks 代码分离去重DynamicImport动态加载js文件Hot-module-replacement开发环境热更新w
一目录结构├──build//构建相关├──config//配置相关├──src//源代码│├──api//所有请求│├──assets//主题字体等静态资源│
接着第一节的demo现在我们尝试整合一些其他资源,比如图像,看看webpack如何处理。在webpack出现之前,前端开发人员会使用grunt和gulp等工具来处理资源,并将它们从 /src 文件夹移动到 /dist 或 /build 目录中。同样方式也被用于JavaScript模块,但是,像webpack这样的工
webpack的打包原理识别入口文件通过逐层识别模块依赖(Commonjs、amd或者es6的import,webpack都会对其进行分析,来获取代码的依赖)webpack做的就是分析代码,转换代码,编译代码,输出代码最终形成打包后的代码什么是loaderloader是文件加载器,能够加载资源文件,并对这些文件进行
上一篇文章我们在一个demo中见到了webpack的身影,如果从未接触过webpack的同学学完了上一篇文章可能会觉得webpack只是一个“翻译官”,但事实上webpack可不仅仅可以‘翻译’代码,事实上,webpack是一个‘打包’工具,‘打包‘才是webpack的核心任务。打开webpack的官网:webpack中
注:本章将配合Vue详细讲解webpack前提条件1.在开始之前,请确保安装了Node.js和npm的最新版本。使用旧版本,你可能遇到各种问题,因为它们可能缺少webpack功能以及/或者缺少相关package包。在cmd中node-v,npm-v可查看对应的版本和安装情况。2.这里会用到ES6的模块化,如果你
前言、之前我认为对于项目的优化无非是从代码上去优化一些东西,比如循环呀函数式调用呀让你的代码看起来更加的简洁容易懂后来我在面试过程中不断有面试官不断地问了我这些问题所以自己就去研究了一下发现并不是我之前想的那样,一个好的webapck优化的胜过于你在整体代码上
##一、组件component###1.什么是组件?组件(Component)是Vue.js最强大的功能之一。组件可以扩展HTML元素,封装可重用的代码组件是自定义元素(对象)###2.定义组件的方式方式1:先创建组件构造器,然后由组件构造器创建组件方式2:直接创建组件###3.组件的分
 #webpack5概述>webpack是一个现代javascript应用程序的**静态模块打包器(modulebundler)**>>vue-cli脚手架环境,集成了webpack,所以才能对各类文件进行打包处理[webpack官网](https://webpack.js.org/) ##webpack能做什么webpack是一个静态模块打包
//这里导入webpack配置,我用对象的形式表示,当然entry属性上定义的文件要有//constconfig=require("./webpack.config");constconfig={entry:'./src/index.js'};const{join,dirname}=require("path");const{readFileSync,writeFileSync}=requi
安装cnpminstallwebpack-bundle-analyzer-D 修改vue.config.jsmodule.exports={chainWebpack:config=>{if(process.env.use_analyzer){//分析config.plugin('webpack-bundle-analyzer')
webpack打包html插件html-webpack-plugin的使用1.创建这样的测试目录结构1)index.html是即将被打包的文件,你可以随便写一些内容2)index.js是打包的入口文件,你可以写或不写内容2.webpack.config.js的代码如下:/***压缩html需要插件:html-webpack=plugin*插件使用方法:
vueinitwebpacktabbar创建vue项目时出现问题vue:无法加载文件C:\Users\dengqian\AppData\Roaming\npm\vue.ps1,因为在此系统上禁止运行脚本。C:\Windows\System32\WindowsPowerShell\v1.0,找到如上路径,以管理员身份运行powershell.exe即可输入set-ExecutionPolicyRemo
在webpack中使用ECharts【官网教程】1、使用如下命令通过npm 安装EChartsnpminstallecharts--save2、全局引用在main.jsimportechartsfrom'echarts'Vue.prototype.$echarts=echarts;3、运用<divstyle="width:60vw;height:280px;"ref="chart"&
如果没有看过我的上一篇文章,请先移步去看一下哈!时隔一年多,之前写的文章感觉大家还挺喜欢的,一直说要更新下一篇。但是一直没有机会,没时间,还有就是,感觉自己的技术,可能不足以支持我继续往下走。但是经过这个一年多的历练,感觉很多东西考虑的会更周全,不负期待!废话说一堆,步入正题
dist文件配置对应的路由名展示这样的效果可以创建一个本地的服务还可以进行代理项目开发是在src里进行代码逻辑编写./表示本地路径/表示绝对路径(nginx需要配置)
 1、用命令创建webpack模板项目vueinitwebpack 项目名,需要选是否的统一选否,所以的依赖手动添加  2、安装依赖vue-router,elementui,sass-loader,node-sass,axios插件安装路由:npminstallvue-router安装elementu
最近想把蘑菇博客部署到k8s上,作为一名java搬砖工,搬砖人不讲码德,biu一下就把后端各模块的dockerfile和chart包copy过来了,很快啊!接下来就可以愉快的使用helm管理蘑菇后端服务部署了。部署完后端服务后,准备制作前端镜像,发现前端打包后,无法动态读取系统环境变量,这很头疼,难不