module: {
rules: [{
test: /\.js$/,
use: {
loader: 'babel-loader',
},
// 规避了对庞大的 node_modules 文件夹或者 bower_components 文件夹的处理
exclude: /(node_modules|bower_components)/,
include: resolve('source')
}]
}
复制代码
module: {
rules: [{
test: /\.js$/,
use: {
// 开启缓存
loader: 'babel-loader?cacheDirectory=true'
},
exclude: /(node_modules|bower_components)/,
include: resolve('source')
}]
}
复制代码
处理第三方库有多种方式,externals、CommonsChunkPlugin、splitChunks、DllPlugin/DLLReferencePlugin 。咱们先说说各类的优劣势html
防止将某些 import 的包(package)打包到 bundle 中,而是在运行时(runtime)再去从外部获取这些扩展依赖(external dependencies)。vue
<script src="https://unpkg.com/element-ui@2.0.8/lib/index.js"></script>
module.exports= {
externals: {
ElementUi: 'ELEMENT' // 主要element-ui保留出来的全局变量是ELEMENT
}
}
import ElementUi from 'ElementUi';
复制代码
经过将公共模块拆出来,最终合成的文件可以在最开始的时候加载一次,便存到缓存中供后续使用。这个带来速度上的提高,由于浏览器会迅速将公共的代码从缓存中取出来, 而不是每次访问一个新页面时,再去加载一个更大的文件。(可是新的webpack中已经被移除,使用的是SplitChunksPlugin)node
new webpack.optimize.CommonsChunlPlugin({
name: string, // or
names: string[],
// 这是 common chunk 的名称。已经存在的 chunk 能够经过传入一个已存在的 chunk 名称而被选择。
// 若是一个字符串数组被传入,这至关于插件针对每一个 chunk 名被屡次调用
// 若是该选项被忽略,同时 `options.async` 或者 `options.children` 被设置,全部的 chunk 都会被使用,
// 不然 `options.filename` 会用于做为 chunk 名。
// When using `options.async` to create common chunks from other async chunks you must specify an entry-point
// chunk name here instead of omitting the `option.name`.
filename: string,
// common chunk 的文件名模板。能够包含与 `output.filename` 相同的占位符。
// 若是被忽略,本来的文件名不会被修改(一般是 `output.filename` 或者 `output.chunkFilename`)。
// This option is not permitted if you're using `options.async` as well, see below for more details. minChunks: number|Infinity|function(module, count) -> boolean, // 在传入 公共chunk(commons chunk) 以前所须要包含的最少数量的 chunks 。 // 数量必须大于等于2,或者少于等于 chunks的数量 // 传入 `Infinity` 会立刻生成 公共chunk,但里面没有模块。 // 你能够传入一个 `function` ,以添加定制的逻辑(默认是 chunk 的数量) chunks: string[], // 经过 chunk name 去选择 chunks 的来源。chunk 必须是 公共chunk 的子模块。 // 若是被忽略,全部的,全部的 入口chunk (entry chunk) 都会被选择。 children: boolean, // 若是设置为 `true`,全部公共 chunk 的子模块都会被选择 deepChildren: boolean, // 若是设置为 `true`,全部公共 chunk 的后代模块都会被选择 async: boolean|string, // 若是设置为 `true`,一个异步的 公共chunk 会做为 `options.name` 的子模块,和 `options.chunks` 的兄弟模块被建立。 // 它会与 `options.chunks` 并行被加载。 // Instead of using `option.filename`, it is possible to change the name of the output file by providing // the desired string here instead of `true`. minSize: number, // 在 公共chunk 被建立立以前,全部 公共模块 (common module) 的最少大小。 }); 复制代码
webpack4中支持了零配置的特性,同时对块打包也作了优化,CommonsChunkPlugin已经被移除了,如今是使用optimization.splitChunks代替。webpack
// webpack.config.js
splitChunks: {
chunks: "async",
minSize: 30000,
minChunks: 1,
maxAsyncRequests: 5,
maxInitialRequests: 3,
automaticNameDelimiter: '~',
name: true,
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true
}
}
}
复制代码
DllPlugin:是基于 Windows 动态连接库(dll)的思想被创做出来的。这个插件会把第三方库单独打包到一个文件中,这个文件就是一个单纯的依赖库。这个依赖库不会跟着你的业务代码一块儿被 从新打包,只有当依赖自身发生版本变化时才会从新打包。ios
DLLReferencePlugin:是基于 Windows 动态连接库(dll)的思想被创做出来的。这个插件会把第三方库单独打包到一个文件中,这个文件就是一个单纯的依赖库。这个依赖库不会跟着你的业务代码。web
一块儿被从新打包,只有当依赖自身发生版本变化时才会从新打包。配置步骤以下:vue-router
const path = require('path');
const webpack = require('webpack');
const CleanWebpackPlugin = require('clean-webpack-plugin');
module.exports = {
entry: {
// 依赖的库数组
vendor: [
'vue/dist/vue.esm.js',
'axios',
// 'element-ui',
'vue-router',
'vuex',
'v-viewer',
'vue-photo-preview',
'mockjs'
]
},
output: {
path: path.join(__dirname, 'htdocs/dist'),
filename: '[name].js',
library: '[name]_[hash]',
},
plugins: [
new CleanWebpackPlugin(['htdocs/dist/vendor-manifest.json', 'htdocs/dist/vendor.js']),
new webpack.DllPlugin({
// DllPlugin的name属性须要和libary保持一致
name: '[name]_[hash]',
path: path.join(__dirname, 'htdocs/dist', '[name]-manifest.json'),
// context须要和webpack.config.js保持一致
context: __dirname,
}),
],
}
复制代码
/ package.json
"scripts": {
"dll": "webpack -p --progress --config ./webpack.dll.config.js"
},
复制代码
module.exports = {
plugins: [
new webpack.DllReferencePlugin({
context: __dirname,
// manifest就是咱们第一步中打包出来的json文件
manifest: require('./htdocs/dist/vendor-manifest.json'),
})
]
}
复制代码
第一种:直接在index.html。,这种方式简单粗暴,针对没有vendor.js没有hash值的,彻底ok,可是若是你打包的vendor.js有hash,每次从新 npm run dll以后若是生成了新的hash,就要手动改这个路径了。vuex
第二种:add-asset-html-webpack-plugin,该插件会将给定的JS或CSS文件添加到Webpack知道的文件中,并将其放入html-webpack-plugin注入到生成的html 的资产列表中。将插件添加 到您的配置中。(可是须要注意的是此插件须要html-webpack-plugin@^2.10.0。在webpack 4+以后,须要先注册AddAssetHtmlPlugin后才 使用内部使用的钩子,而先前版本的webpack对此 并不关心。HtmlWebpackPluginhtml-webpack-plugin-before-html-generation。)npm
可是我在操做的时候遇到一个很奇葩的坑,element-ui被dllPlugins以后,el-table不生效,是的不生效,页面也么有报错,样式都还存在,可是就是页面展现不出来table。编程
我看到element-ui的issues上也有人遇到这样的状况,可是如今尚未一个解决方案,很难受。
网上有不少解决办法,可是都没有根治我这个问题,最后的解决方案是,单独的使用table,项目重写table。这样的方法也有一个弊端,就是当前只是发现了table不能正常使用,可是若是还有其余 组件不行,也须要重写,这样的成本就很好了。因此,最后项目选择是不打包element-ui(无奈之举)。期待这个问题被解决。
webpack 是单线程的,就算此刻存在多个任务,你也只能排队一个接一个地等待处理。这是 webpack 的缺点,好在咱们的 CPU 是多核的,Happypack 会充分释放 CPU 在多核并发方面的优点, 帮咱们把任务分解给多个子进程去并发执行,大大提高打包效率。
HappyPack 的使用方法也很是简单,只须要咱们把对 loader 的配置转移到 HappyPack 中去就好,咱们能够手动告诉 HappyPack 咱们须要多少个并发的进程:
const HappyPack = require("happypack");
// 手动建立进程池
const happyThreadPool = HappyPack.ThreadPool({ size: os.cpus().length });
module.exports = {
plugins: [
new HappyPack({
// 这个HappyPack的“名字”就叫作happyBabel,和楼上的查询参数遥相呼应
id: 'happyBabel',
// 指定进程池
threadPool: happyThreadPool,
// 输出日志
verbose: true,
loaders: ['babel-loader?cacheDirectory']
}),
]
};
复制代码
这个插件能够帮助具备许多入口点的项目加速构建。随Webpack提供的uglifyjs插件在每一个输出文件上按顺序运行。这个插件与每一个可用CPU的一个线程并行运行uglify。这可能会致使显著减小构 建时间,由于最小化是CPU密集型的。简单点来讲就是顺序运行改成并行,因此大大提高了构建速度。
// const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const ParallelUglifyPlugin = require('webpack-parallel-uglify-plugin');
module.exports = {
plugins: [
new ParallelUglifyPlugin({
cacheDir: 'cache_dir',//用做缓存的可选绝对路径。若是未提供,则不使用缓存。
sourceMap: config.build.productionSourceMap, //可选布尔值。是否为压缩后的代码生成对应的Source Map(浏览器能够在调试代码时定位到源码位置了),这会减慢编译速度。默认为false
uglifyJS: {
output: {
comments: false,//是否保留代码中的注释,默认为保留
},
warnings: true,//是否在UglifyJS删除没有用到的代码时输出警告信息,默认为false
compress: {
drop_console: true,//是否删除代码中全部的console语句,默认为false
collapse_vars: true,//是否内嵌虽然已经定义了,可是只用到一次的变量, 默认值false
reduce_vars: true,//是否提取出现了屡次可是没有定义成变量去引用的静态值,默认为false
}
},
})
]
};
复制代码
做者优化这个项目以前,开发人员也是分组打包,可是是一个路由打包一个js文件,致使最后的结果就是,生产了60+的js文件,在进行批量发布时,哪速度叫一个感人,做者进行了一个简单的操做优化, 就是根据名称分组打包,最后打包下来只有10+的js,而且我发现,60+文件打包的大小比10+文件的整体大小要大一些。哈哈哈,无心间发现的。
这个优化其实就是一个平常须要注意的问题,可是能间接的提高webpack的打包效率、打包大小的优化。
因此咱们在平常的操做中多使用函数式编程,来提高webpack的打包效率和打包大小。
element-ui被dllPlugins以后,el-table不生效。求大神解决。项目依赖版本以下: