-
Notifications
You must be signed in to change notification settings - Fork 383
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
webpack打包bundle.js体积大小优化 #65
Comments
写得真棒, |
babel-polyfill怎么抽出来的呢,如果我不把babel-polyfill打包进去,打包的后的页面会报错 |
直接不要在代码中require('babel-polyfill'),然后在html文件中直接引用polyfill(注意,polyfill必须在你写的js前引用) 。至于为什么可以这样做,你可以看看官网的说明。https://babeljs.io/docs/usage/polyfill/ @beiciye |
朋友你好,我使用 externals: {
'react': 'React',
'react-dom': 'ReactDOM'
} 的方式将 react 包 排除,但是只能在页面使用 react 与 react-dom 的文件包,无法使用 react-with-addons 包。提示 |
@codelegant “ReactDOM is not defined"这个错误是哪一行代码报的错,截图我看看。 |
@codelegant 还有你在html引用了那些react相关的js文件?我看你的邮件你是只引用了react-with-addon.js? |
@codelegant 你这样只引用react-with-addon.js是不对了。因为react从版本v15开始,就把react-dom相关的部分抽离出核心,放在react-dom上面了,具体的你可以参考react在github上的release note,或者这里。 另外,第97行代码的意思其实是将你引入的React-DOM.js重新包裹输出到webpack自己的模块系统中,模块的id为3。 |
倘若我使用了 |
@codelegant react-with-addons.js里面已经包含许多react-addon(插件),所以你只要引用react-with-addon.js就可以使用这些插件了。包含的插件列表可以参考这里。 https://facebook.github.io/react/docs/addons.html |
那意思是要一个使用了 add-ons 插件的 react 应用,需要在页面中引入 react react-dom react-with-addons 三个包? |
@codelegant 不是! 只需要引react-dom和react-with-addons,不需要再引react,因为react-with-addons就是带插件版本的react,react.js是不带插件版本的react. |
多谢,我还以为 react-with-addons 是包括 react-dom 的,受教了。 |
再请教一个问题,我使用 ES6 的方式引入插件: import ReactCSSTransitionGroup from 'react-addons-css-transition-group'; webpack 中该如何配置才能使用打包后的文件能够在页面上使用 react-with-addons ?我的配置: externals: {
'react': 'React',
'react-dom': 'ReactDOM',
'react-addons-css-transition-group':'ReactCSSTransitionGroup'
} 然后页面出错: |
@codelegant 你这样写是有问题的,如果你直接require(你import也一个样)react-addons-css-transition-group,由于react-addons-css-transition-group会重新require react lib文件夹下的很多东西,所以你这样做是没法将react分离的。正确的做法上面已经提到了,你在引入了react-with-addons.js之后。
这样就可以拿到ReactCSSTransitionGroup了。 |
使用 |
@codelegant 我并不使用HMR,因为我对这个东西还没完全理解。我是采用结合webpack自带的watch和browsersync来实现热加载的功能的。另外,即便你适用web-dev-server,HMR这些东西,我并不认为你就能适用 'import ReactCSSTransitionGroup from 'react-addons-css-transition-group'写法。因为你在项目开发过程中,React.addon.js本身是不会发生改变的,自然无需watch它。 |
刚才试验,用 react 外引的方式 HMR 工作正常,只不过 react-hot-loader 没法用。以后坑还会很多,时不时的会叨扰兄台,还望勿怪。 |
@youngwind 你好,想请教下如果我使用预编译版本的react-with-addons.js文件,他的插件列表中并没有ReactInputSelection和ReactMount这两项,这该怎么处理? |
库里面的依赖,可以标记成peerdependencies吧 |
贴下我的优化方式,部分polyfill和shim是为了兼容IE(这种预编译版本兼容至IE9,如果要兼容IE9以下,需要自行编译),如果不需要的就不用加了 externals: {
'react': 'React',
'react-dom': 'ReactDOM',
'redux': 'Redux',
'redux-thunk': 'ReduxThunk',
'react-redux': 'ReactRedux',
'react-addons-css-transition-group': 'React.addons.CSSTransitionGroup',
'react-router': 'ReactRouter',
'react-router-redux': 'ReactRouterRedux',
'react-bootstrap': 'ReactBootstrap',
'babel-polyfill': 'window', // polyfill 直接写 {} 也是可以的
'es5-shim': 'window',
'whatwg-fetch': 'fetch',
'node-uuid': 'uuid',
'console-polyfill': 'console'
}, <script src="https://cdn.bootcss.com/es5-shim/4.5.9/es5-shim.min.js"></script>
<script src="https://cdn.bootcss.com/babel-polyfill/6.16.0/polyfill.min.js"></script>
<script src="https://cdn.bootcss.com/react/15.3.2/react-with-addons.min.js"></script>
<script src="https://cdn.bootcss.com/react/15.3.2/react-dom.min.js"></script>
<script src="https://cdn.bootcss.com/redux/3.6.0/redux.min.js"></script>
<script src="https://cdn.bootcss.com/react-redux/4.4.5/react-redux.min.js"></script>
<script src="https://cdn.bootcss.com/react-router/3.0.0/ReactRouter.min.js"></script>
<script src="https://cdn.bootcss.com/react-router-redux/4.0.6/ReactRouterRedux.min.js"></script>
<script src="https://cdn.bootcss.com/react-bootstrap/0.30.6/react-bootstrap.min.js"></script>
<script src="https://cdn.bootcss.com/redux-thunk/2.1.0/redux-thunk.min.js"></script>
<script src="https://cdn.bootcss.com/fetch/1.0.0/fetch.min.js"></script>
<script src="https://cdn.bootcss.com/node-uuid/1.4.7/uuid.min.js"></script>
<script src="https://cdn.bootcss.com/console-polyfill/0.2.3/index.min.js"></script> 经过上述精简后 bundle从800多K减少到160多K 如果有源码级调试或者其他需求,可以写两个webpack配置,调试构建使用不带externals,生产构建使用externals |
antd库怎么抽出来呢? 我的项目里面用了antd库, 我单独引用antd.js, 用externals 配置了antd, 打包完发现不能运行 |
good!bundle小了1M,多谢! |
尝试了 externals,虽然大小变小了,构建速度变快了,但是手机加载变得极慢(特别是用了 antd、recharts 的 CDN)。还是要按需加载,减少手机解析 js 的时间(缓存变的不重要了)。 |
已解决,感谢。
Ian Hu <[email protected]> 于2019年8月12日周一 上午9:00写道:
… 想问下,这样子的话,如何使用import React from 'react'
externals: {
'react': 'React',
'react-dom': 'ReactDOM'
}
[image: image]
<https://user-images.githubusercontent.com/16217324/62758043-cc3b6b00-baaf-11e9-8ca5-1e62a5a6b28d.png>
要把script标签引入的React的js放在bundle之前引入,否则就会出现未定义\
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#65?email_source=notifications&email_token=AD3XJ3CQ63357EOA6TBSQS3QECY2PA5CNFSM4CBM6MK2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD4BMTCY#issuecomment-520276363>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AD3XJ3B5TFIZ3LPQKTFOKCTQECY2PANCNFSM4CBM6MKQ>
.
|
请问一下,nuxt框架上的webpack优化 使用cdn方式有研究过吗? |
问题
最近在做一个项目,用的是react+redux+webpack,但是发现写着写着build出来的bundle.js(压缩前)居然已经有2.3M左右!开玩笑!我自己写的src目录底下的文件总大小也不过100多K,这也太夸张了吧。。。于是开始寻找优化的方法。
分析
先分析一下历史原因。
第一,在用webpack之前,做的项目都是jquery+后端渲染,一个页面请求巨多的js和css,导致性能问题。后来引入了react开发单页面应用的同时,使用webpack进行打包。所以,其实我们是很少经历说用webpack去打包jquery+后端渲染这样的项目的。
第二,由于开发的是单页面应用,不存在设置多个entry的做法,只能把js都build到一个bundle.js中(这里先不考虑根据router跳转按需请求的做法),所以最后build出来的唯一的bundle.js非常巨大,什么东西都往里面塞。
这样子导致的问题包括:
优化开始
其实当初用webpack是为了减少请求数,但是后来没能平衡好请求数和单个请求体积的问题。
如果能把里面常用的部分提取出来,放到cdn上缓存起来就好了
我觉得解决问题的第一步是:
分析巨大的bundle.js,看看里面都有啥,各个部分占据的体积是多少?
原始的供耕火种
先从webpack着手,
这个命令可以在打包的时候显示所有打包的模块以及他们的体积,并且按照体积从小到大进行排序。如图。
我们翻到最后就能看到占据体积最大的module
当然,这里显示的是我已经优化好的。
还原一下一开始场景:
我一开始在项目中引用了lodash,一个lodash400k啊!不仅如此,我还用了一个自己写的npm包,那个npm包也引用了lodash,关键是两个lodash依赖的版本还不一样。两个加起来就有900k了。。。(让我静一会儿。。。)这深深让我意识到前端的工具库可不能像后端那样随便引,要考虑体积啊!
然后接着分析,我只不过有了lodash很少一部分功能而已,没必要引用整个lodash包吧,所以又发现了lodash其实是有很多自己单独的包可以安装的。如图
不错,用了单独安装的包之后体积减少了很多。但是我还是觉得减少的不够,所以我想使用is.js这玩意儿,但是死活没有搞定在webpack中打包出错的问题,见这儿。
到这儿我心好累。。。心一横,不就几个判断和小工具嘛,最后我自己用原生的写了。。。所以就没有使用lodash和is.js。
工具范儿
ok,到这儿总算是“轻松加愉快”地解决了大头。然后,再分析剩余的1.3M左右的bundle.js。总不能一直这样用肉眼看上面终端输出的module列表吧,我知道肯定有人帮我们干了这事儿,坚持不懈的我找到了两个工具。
一开始用第一个工具的时候完全不会,我以为把bundle.js上传上去就好了,谁知道它要传什么json文件。(好歹你也给点提示啊。。。)等我找到第二个工具之后才发现需要生成一个json文件用于分析。
这两个工具做得实在太棒了!特别是第二个。
有了工具干起活来就特别带劲!ok,现在不用看我都知道在剩余的1.3M当中占大头的肯定是react,压缩前600k呢!怎么把它从bundle.js搞出来呢?也是经历了一番波折。
最后我的解决方案:
第一,修改webpack.config.js
第二,在html文件中单独引react.js
参考资料:
目前为止,我们已经成功把react从bundle.js中提取出来,这样子我们就可以把react单独缓存起来了!我高高兴兴的重新分析bundle.js。
WTF!为什么里面还包含这么多react/lib目录下面的文件?加起来又是好几百k呢!如图。(没有截那种分析工具的图,就拿终端的将就着看吧。)
又是react-css-transition-group
因为在项目中需要动画,用到了react-css-transition-group,react从v0.15版本开始就把addon从核心中剥离出来,具体的可以参考 #61 里面的安装部分。
我用第一个工具仔细分析了ReactDOMComponent.js的来源,一层一层地往上追溯,最后居然发现这个东西居然是因为react-css-transition-group引入的。。。我打开react-css-transition-group包看它的源码,发现只有一行。。。
其实这家伙又重新指回去了react库。我不就想用一个动画插件而已嘛。。至于付出几百k的代价吗?后来我一想,react虽然把addon从核心中移除了,但是react一直有一个带插件版本啊,我直接用带插件版本不就好了吗?
一对比,发现react-with-addons.js只比react.js大50k(压缩前),perfect!所以我又把react换成了带插件版本的,react-css-transition-group换一种引用方式。
到这儿,文件大小已经控制在500k左右了。
babel-polyfill的坑
接着分析,发现babel-polyfill是个大头啊,200多k呢!我记得当初我引这个ployfill的时候是因为我在前端用到了co库,那时候引入了ployfill。其实我对babel-ployfill的了解很少,并不知道为什么一定要引入这个东西。以后有时间再研究。不过babel官网中提到这个东西可以单独引用,那就抽离吧!又可以多缓存200多k。
尾声
最后,我又用了抽离react一样的方法抽离了react-dom,react-router,history,redux,react-redux这几个常用的module,具体的webpack配置如下:
最后将体积(压缩前)控制在170k,其中src代码占100k,成果还不错。
遗留问题
The text was updated successfully, but these errors were encountered: