moment
库,有没有发现引入moment以后,项目build完的文件大小明显大了很多,下面就来分析一下缘由, 以及如何作优化。
首先看下代码结构react
import React from 'react'
import { render } from 'react-dom'
import moment from 'moment'
const App = () => {
const date = new Date()
return (
<div>
<h1>{date.toLocaleDateString()}</h1>
<h1>{moment().format('YYYY-MM-DD')}</h1>
</div>
)
}
render(<App/>, document.getElementById('app'))
复制代码
上面两张图片分别是没用moment和用了moment编译的结果webpack
只有几行代码, 编译出来的文件相差那么大。网上搜了一波才知道, 打包时把全部的locale都打包进去了, 初步解决方案是用webpack.IgnorePlugin来处理。web
IgnorePlugin又是作了什么操做?正则表达式
// webpack.config.js
...
plugins: [
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/) // 配置忽略规则
]
复制代码
原理:在webpack编译阶段, 若是引入的文件路径匹配/^\.\/locale$/
,则会忽略这个文件, 也就不会被打包进去。json
moment
包编译后的文件并未找到彻底匹配/^\.\/locale$/
这个正则的引入语句,只有aliasedRequire('./locale/' + name)
这条语句和locale相关, 却又和正则匹配不上, 却是在moment
的src源文件中有import ... from './locale'
。 可是在moment
的package.json
中main是指向编译后的文件并非src文件,这就奇了怪了, 因而debug IgnorePlugin看了一下。./locale
, 眼瞎了仍是webpack的问题?按照dependencies的位置1853行查看moment编译后的文件, 定位到了确实是 aliasedRequire('./locale/' + name)
, 怎么回事?require('./locale/' + name)
此类表达式时,webpack 会查找目录 './locale/'
下符合正则表达式 /^.*\.$/
的文件。因为 name 在编译时仍是未知的,webpack 会将每一个文件都做为模块引入到 bundle 中, 这就是为何引入moment以后, 编译完的文件为何会那么大的缘由。moment.locale('zh-cn')
以后, format以后的日期仍然是英文的,语言没有切换过来。moment-locales-webpack-plugin
new MomentLocalesPlugin({
localesToKeep: ['zh-cn'],
})
复制代码
en
,它必然会被打包进去, 若是须要配置其余语言,能够经过localesToKeep
来配置, 其余没用到的语言包也就不会被打包进去了。en
除外)...
if (localesToKeep.length > 0) {
var regExpPatterns = localesToKeep.map(function(localeName) {
return localeName + '(\\.js)?';
});
return new ContextReplacementPlugin(
/moment[\/\\]locale/,
new RegExp('(' + regExpPatterns.join('|') + ')$') // 配置webpack编译阶段的查找规则, 即指定语言包
);
} else {
return new IgnorePlugin(/^\.\/locale$/, /moment$/);
}
...
复制代码
到此结束。bash
水平有限,文中有错误之处,还望大佬指正。app