1 参考文章

彻底解决 webpack 打包文件体积过大

webpack4提升180%编译速度

详解webpack4之splitchunksPlugin代码包分拆

webpack v4 中的断舍离

开发工具心得:如何 10 倍提高你的 Webpack 构建效率

Webpack打包构建太慢了?试试几个方法

上手webpack4并进阶?来看这里~

注意合并 webpack.config.js 文件的时候,把 commonConfig 放在前面 否则一些地方会报错
module.exports = merger(commonConfig,prodConfig);

2: webpack4中的 optimization.runtimeChunk的作用是什么?

首先看参考文章:
优化持久化缓存的, runtime 指的是 webpack 的运行环境(具体作用就是模块解析, 加载) 和 模块信息清单,
模块信息清单在每次有模块变更(hash 变更)时都会变更, 所以我们想把这部分代码单独打包出来,
配合后端缓存策略, 这样就不会因为某个模块的变更导致包含模块信息的模块(通常会被包含在最后一个 bundle 中)缓存失效.
optimization.runtimeChunk 就是告诉 webpack 是否要把这部分单独打包出来.

假设一个使用动态导入的情况(使用import()),在app.js动态导入component.js

const app = () =>import('./component').then();

build之后,产生3个包。

0.01e47fe5.js
main.xxx.js
runtime.xxx.js

其中runtime,用于管理被分出来的包。下面就是一个runtimeChunk的截图,可以看到chunkId这些东西。

...

function jsonpScriptSrc(chunkId) {
/******/ return __webpack_require__.p + "" + ({}[chunkId]||chunkId) + "." + {"0":"01e47fe5"}[chunkId] + ".bundle.js"
/******/ }

...

如果采用这种分包策略

当更改app的时候runtime与(被分出的动态加载的代码)0.01e47fe5.js的名称(hash)不会改变,main的名称(hash)会改变。
当更改component.js,main的名称(hash)不会改变,runtime与 (动态加载的代码) 0.01e47fe5.js的名称(hash)会改变。

总结一下:

runtime.js文件相当于动态文件的索引文件,相当于一个文件夹中的index索引文件,告诉main.js要引用的文件的名字

这样app.js 变化的时候 由于不影响 componment.js 所以生成的0.01.js 和runtime.js 不会发生变化;

当 componment.js 发生变化的时候,生成的0.01.js要发生变化,同时索引文件 runntime.js 也会发生变化。但是main.js引用的是runntime.js 则不会发生变化

---

3  使用 splitchunksPlugin 提取公共代码

optimization:{
splitChunks: {
chunks: 'all',//同步异步全都打包
minSize: 30000,//打包的库或者文件必须大于这个字节才会进行拆分
minChunks: 1,//规定当模块在生成的js文件(trunk)中被调用过多少次的时候再进行拆分
maxAsyncRequests: 5,
maxInitialRequests: 3,
automaticNameDelimiter: '~',//如果不写filename 默认名字 组名~[name]
name: true,
cacheGroups: {//缓存组,因为需要打包完成之后,在把所有要拆分的代码合并拆分,所以先要缓存
vendors: {
test: /[\\/]node_modules[\\/]/, //如果上面chunks定为all,就是找到所有的import文件,看他是不是调用于 node_modules 文件夹 是的话就拆分
priority: -10,//优先级 比如同时符合vender 和 default 这个优先级高 所以存在这里
filename: 'vendors.js', //拆分后打包的文件名字
},
default: {//像文件中 import进来的文件 如果不在 node_modules文件夹中 则走默认组,打包出的文件名字是 common.js
priority: -20,
minChunks: 2,
reuseExistingChunk: true,//比如a.js 引用了 b.js;如果b.js在之前已经被拆分过,则这里不再对其进行拆分
filename: 'common.js'
}
}
}
}

为了支持异步js,

npm install --save-dev @babel/plugin-syntax-dynamic-import

记得修改 .babelrc

{
"presets":[
["@babel/preset-env",{
"useBuiltIns":"usage",
"corejs":2,
"targets":{
"browsers":[">1%","last 2 version","not ie <= 8"]
}
}]
],
"plugins": ["@babel/plugin-syntax-dynamic-import"]
}

注意:

minSize: 指的是打包前的文件大小,并且指的是 组成 commonjs的所有文件的和的大小,而不是其中一个文件的大小;
比如 组成commonjs的三个子组件是 a.js b.js c.js 分别是10k,则minSize需大于 30k 才不会打包这几个文件,
而不是 10k。
1: chunks: "initial"-- 表示只从入口模块进行拆分
1.1 有异步引入的js文件:三个入口文件+公共的common文件+子组件【相当于原来的文件分别单独打包】
1.2 全是同步引入js文件:三个入口文件+公共的common文件{包括了子组件}
2: chunks: "async" -- 表示只从异步加载得模块(动态加载import())里面进行拆分
2.1 有异步引入的js文件:三个入口文件【common文件被重复打包到入口文件中】+子组件
2.2 全是同步引入js文件:三个入口文件{每个文件均包括了common和三个子组件}
3: chunks: "all"
3.1 有异步引入的js文件:三个入口文件+common文件+三个子组件【相当于原来的文件分别单独打包】
3.2 全是同步引入js文件:三个入口文件+common文件【包括common本身和引入的子组件】

4: 使用 DLLPlugin 提取第三方不变化的代码库:

 
splitchunksPlugin 每次打包的时候还是会去处理一些第三方依赖库,只是它能把第三方库文件和我们的代码分开掉,生成一个独立的js文件。但是它还是不能提高打包的速度。

DLLPlugin 它能把第三方库代码分离开,并且每次文件更改的时候,它只会打包该项目自身的代码。所以打包速度会更快。

DLLPlugin:
vendor.dll.js文件:存放第三方库
venfor-manifest.json文件:包含所有代码库的一个索引
DllReferencePlugin:在webpack.config.js 文件中使用的
作用是用该插件读取 venfor-manifest.json文件 查询第三方库
 
首先编写webpack.dll.js文件:
const path = require('path');
const DllPlugin = require('webpack/lib/DllPlugin');
const {CleanWebpackPlugin} = require('clean-webpack-plugin'); module.exports = {
mode:'production',
// 入口文件
entry: {
// 项目中用到该两个依赖库文件
vue: ['vue']
},
// 输出文件
output: {
// 文件名称
filename: '[name].dll.js',
// 将输出的文件放到dist目录下
path: path.resolve(__dirname, '../static'), /*
存放相关的dll文件的全局变量名称,比如对于jquery来说的话就是 _dll_jquery, 在前面加 _dll
是为了防止全局变量冲突。
*/
library: '[name]_library'
},
plugins: [
new CleanWebpackPlugin(), //注意在webpack4 中 不需要定于删除哪个文件夹 默认会根据output中生成的path路径删掉
// 使用插件 DllPlugin
new DllPlugin({
/*
该插件的name属性值需要和 output.library保存一致,该字段值,也就是输出的 manifest.json文件中name字段的值。
比如在jquery.manifest文件中有 name: '_dll_jquery'
*/
name: '[name]_library',
context:__dirname, //context (可选): manifest文件中请求的上下文,默认为该webpack文件上下文
/* 生成manifest文件输出的位置和文件名称 */
path: path.join(__dirname, '../static/', '[name].manifest.json')
})
]
};
在 webpack.prod.js 文件中调用索引文件
 
const DllReferencePlugin = require('webpack/lib/DllReferencePlugin');
const proConfig = {
plugins:[
new DllReferencePlugin({
context:__dirname,
manifest:require('../static/vue.manifest.json')
})
]
}

然后增加 package.json 文件:

 "dll": "webpack --config ./build/webpack.dll.js --hide-modules --progress"

最后在模版文件中增加引用:

 <script type="text/javascript" src="../static/vue.dll.js"></script>

所以先执行 npm run dll,在执行npm run build

但是这样修该模版文件不太好,所以引入插件:

const AddAssetHtmlPlugin   = require('add-asset-html-webpack-plugin');
plugins:[
new AddAssetHtmlPlugin({
filepath: require.resolve('../static/vue.dll.js'),//相当于path.join(__dirname, '../static/vendordev.dll.js')
includeSourcemap: false
})
]

注意:

1:  html-webpack-include-assets-plugin  和 add-asset-html-webpack-plugin 的区别

两个插件都是把规定的文件插入到html中:

主要的不同是 html-webpack-include-assets-plugin  不会copy文件,而 add-asset-html-webpack-plugin 会copy文件,什么意思呢?

使用 add-asset-html-webpack-plugin 后,会把引入的  filepath: require.resolve('../static/vue.dll.js') 自动引入到 dist 文件夹中,而 html-webpack-include-assets-plugin 则不会;

所以在dev环境下,直接把vue.dll.js 引入dist目录下即可,所以使用  add-asset-html-webpack-plugin;而在production环境下,要把 vue.dll.js 放在dist/lib 文件夹下,所以使用CopyWebpackPlugin 复制vue.dll.js文件,配合 html-webpack-include-assets-plugin 插入html中;

所以分为dev和product环境:

const htmlWebpackIncludeAssetsPlugin = require('html-webpack-include-assets-plugin');
const AddAssetHtmlPlugin = require('add-asset-html-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin'); //dev环境中,该插件会把 vue.dll.js 文件复制到当前路径下
new AddAssetHtmlPlugin({
filepath: require.resolve('../static/vue.dll.js'),//相当于path.join(__dirname, '../static/vendordev.dll.js')
includeSourcemap: false,
}), //production 环境中
// 1 需要把 dll 文件复制到打包的 dist/lib 文件夹下 -- CopyWebpackPlugin
// 2 html中引入 dist/lib 下的dll 文件 -- htmlWebpackIncludeAssetsPlugin new htmlWebpackIncludeAssetsPlugin({ //这个插件是把vue.dll.js 插入到 html 中
assets:['./lib/vue.dll.js'],
append:false
}),
new CopyWebpackPlugin([ //文件复制到打包的 dist/lib 文件夹下
{ from: path.join(__dirname, "../static/vue.dll.js"), to: path.join(__dirname, "../dist/lib/vue.dll.js") }
]),

注意2:

这里引入  AddAssetHtmlPlugin 你会发现即使不使用:

new DllReferencePlugin({
context:__dirname,
manifest:require('../static/vue.manifest.json')
})

页面也可以使用vue。

那么  DllReferencePlugin  的作用是什么呢?

我们看打包生成的文件:

情况1: 不使用 DllReferencePlugin:

可以看出,index.js 文件中使用的vue居然还是来自 node_modules 说明并没有把vue第三方库剔除;

对比使用DllReferencePlugin :

发现index中已经没有 vue 第三方库,但是页面仍旧能打开,说明使用的是 dll 文件。

再来看 DllReferencePlugin 的作用:

有了映射文件,在webpack打包的时候就可以结合映射文件以及生成的全局变量,来对需要打包的源代码进行分析。
一旦发现你打包的源代码里面用到了映射文件中已有的文件,则直接使用vendors.dll.js 中的内容,而不会去node_modules里引入该模块

5. 引入的loader一定要加上 exclude和include 可以大幅降低打包的代码文件大小

6.  使用别名优化:

resolve:{
extensions:['.js','.vue','.json'],
alias:{
"@":path.resolve('src')
}
}

使用extensions省略后缀名字;使用alias给src加上别名,这样可以简化html中的路径,比如:

pages/index/index.vue 中要使用 assest/imgs/logo.png 的图片:

<img src="../../assest/imgs/logo.png" alt="" class="img-box">

可以简化成:

<img src="@/assest/imgs/logo.png" alt="" class="img-box">

类似的:

//简化前
import Chinese from '../../component/chinese.vue';
//简化后
import Chinese from '@/component/chinese.vue';

但是对于css注意,在引用路径的字符串前面加上 ~ 的符号,如:@import “~Css/…”。webpack 会以~符号作为前缀的路径视为依赖模块去解析

background: url('~@/assest/imgs/logo.png');
7 :vue-router的问题

代码:

import VueRouter from 'vue-router'
import routers from './routers' Vue.use(VueRouter) const router = new VueRouter({
mode: 'history',
routers
})

原因:
routes:不是routers

解决办法:
routers改为routes即可。

8.解决webpack中css独立成文件后图片路径错误的问题

说明:此配置针对webpack4+

配置img图片路径问题:

output:{
filename:'js/[name].[chunkhash].js',
path:path.resolve(__dirname,'../dist'),
},
//module
{
test:/\.(png|gif|jpeg|jpg)$/,
use:[
{
loader:'url-loader?cacheDirectory=true',
options:{
name:'img/[name].[ext]',
limit:1024
}
}
]
},
//plugins
new MiniCssExtractPlugin({
filename: devMode ? '[name].css' : 'css/[name].[contenthash].css',
chunkFilename: devMode ? '[name].css' : 'css/[name].[contenthash].css',
})

生成的图片会在css文件中: css/img/logo.png 这样的话 找不到该图片,因为生成的图片路径应该是 img/logo.png

如果修改output的配置中加入一个 publicPath: '../' 配置,则所有的css文件和js的路径都会变化,所以应该只处理css文件,设置css文件中的公共路径:

output:{
filename:'js/[name].[chunkhash].js',
path:path.resolve(__dirname,'../dist'),
},
//module
{
test:/\.scss$/,
use:[
{
loader:MiniCssExtractPlugin.loader,
options:{
publicPath:'../'
}
},
{
loader:'css-loader',
options:{
importLoaders:2,
}
},
'postcss-loader',
'sass-loader'
]
},
{
test:/\.(png|gif|jpeg|jpg)$/,
use:[
{
loader:'url-loader?cacheDirectory=true',
options:{
name:'img/[name].[ext]',
limit:1024
}
}
]
},
//plugins
new MiniCssExtractPlugin({
filename: devMode ? '[name].css' : 'css/[name].[contenthash].css',
chunkFilename: devMode ? '[name].css' : 'css/[name].[contenthash].css',
})

9 为了避免不同路由页面间样式冲突,css样式要加 scoped

<style lang="scss" scoped>
否则 两个路由中对同一个div做不同的样式,后面的样式会覆盖掉前一个路由页面的样式。
 
10: 使用 splitchunksPlugin 提取公共组件和代码不生效,要注意入口js是否使用了异步加载
比如路由js:
import Home from "./view/home";
const ProInsight = () => import(/* webpackPrefetch: true */ /* webpackChunkName: 'proInsight' */ "./view/proInsight");
const ProTarget = () => import(/* webpackPrefetch: true */ /* webpackChunkName: 'proTarget' */ "./view/proTarget"); Vue.use(VueRouter); const routes = [
{ path: "/", name: "home", component: Home },
{ path: "/proInsight", name: "proInsight", component: ProInsight },
{ path: "/proTarget", name: "proTarget", component: ProTarget }
];

中,首页入口 home文件没有使用异步加载,则该组件所有引用的公共代码,都会被打包到home中,而不会提取出来,

所以,home这个组件也要改成异步加载的形式。这样所有的公共代码才能被提取出来。

 
11. 打包时,报一堆警告:
 
 
stats: {
warningsFilter: (warning) => /Conflicting order between/gm.test(warning),
children: false
}

webpack4 打包优化的更多相关文章

  1. vue cli3使用webpack4打包优化

    去掉console.log,以及开启gzip const CompressionPlugin = require('compression-webpack-plugin');//引入gzip压缩插件 ...

  2. webpack4.0打包优化策略整理小结

    本文转载于:https://www.jb51.net/article/137449.htm 介绍了webpack4.0打包优化策略整理小结,分享给大家,具体如下: webapck4 新特性介绍-参考资 ...

  3. webpack4打包nodejs项目进阶版——多页应用模板

    前段时间我写了个打包nodejs项目的文章,点击前往 但是,问题很多.因为之前的项目是个历史遗留项目,重构起来可能会爆炸,当时又比较急所以就写个的适用范围很小的webpack的打包方法. 最近稍微得空 ...

  4. 多页应用 Webpack4 配置优化与踩坑记录

    前言 最近新起了一个多页项目,之前都未使用 webpack4 ,于是准备上手实践一下.这篇文章主要就是一些配置介绍,对于正准备使用 webpack4 的同学,可以做一些参考. webpack4 相比之 ...

  5. webpack 打包优化的四种方法(多进程打包,多进程压缩,资源 CDN,动态 polyfill)

    如今,webpack 毫无疑问是前端构建领域里最耀眼的一颗星,无论你前端走哪条路线,都需要有很强的webpack 知识.webpack 的基本用法这里就不展开讲了.主要探讨一下如何提高 webpack ...

  6. 小型Web页打包优化(下)

    之前我们推送了一篇小型Web项目打包优化文章,(链接),我们使用了一段时间, 在这过程中我们也一直在思考, 怎么能把结构做的更好.于是我们改造了一版, 把可以改进的地方和可能会出现的问题, 在这一版中 ...

  7. 记一次webpack打包优化

    未进行打包优化的痛点: 随着项目的不断扩大,引入的第三方库会越来越多,我们每次build的时候会对所有的文件进行打包,耗时必定很长,不利于日常开发. 解决思路: 第三方库我们只是引入到项目里来,一般不 ...

  8. webpack原理探究 && 打包优化

    在做vue项目和react项目时,都用到了webpack.webpack帮助我们很好地提高了工作效率,但是一直以来没有对其原理进行探究,略有遗憾. 因为使用一个工具,能够深入了解其原理才能更好地使用. ...

  9. VUE_shop(第十天)项目的打包优化

    项目的打包优化 1.添加页面的加载效果 1.首先安装运行依赖nprocess,在main.js文件中的axios拦截器拦截请求的时候调用Npeocees.start. 在拦截响应的时候调用nproce ...

随机推荐

  1. .net core中关于System.Text.Json的使用

    在.Net Framework的时候序列化经常使用Newtonsoft.Json插件来使用,而在.Net Core中自带了System.Text.Json,号称性能更好,今天抽空就来捣鼓一下. 使用起 ...

  2. linux ubuntu 网卡配置---固定IP

    需要修改/etc/network/interfaces和/etc/resolvconf/resolv.conf.d/base两个文件. 1) /etc/network/interfaces文件: 首先 ...

  3. [ES] - 图形化界面工具

    推荐更新: Windows平台为 ElasticSearch 6.x 安装 Head 客户端插件 elasticsearch-head A web front end for an Elasticse ...

  4. Quartz.Net—JobBuilder

    JobBuilder JobBuilder是一个建造者模式,链式建造.通过静态方法构建一个JobBuilder实例,然后再调用类方法Build()创建一个IJobDetail的实现. 1.静态方法 p ...

  5. django初识1

    django django初识 django的本质就是基于socket通信 一.127.0.0.1 本地回环地址 后面:8001是端口号 /ppt是根目录下的ppt子网页 二./当前网站的客户端(根目 ...

  6. python学习-57 logging模块

    logging 1.basicConfig方式 import logging # 以下是日志的级别 logging.debug('debug message') logging.info('info ...

  7. 网络地址转换(NAT)

    NAT是解决ipv4地址短缺的方案之一 NAT是将位于子网中的主机与外网连通,子网中所有的主机都可以通过路由器的网络地址转换访问外网.对于外网来说该路由器相当于一台完整的主机,子网内所有主机对外网的访 ...

  8. hadoop mapper reducer

    Local模式运行MR流程------------------------- 1.创建外部Job(mapreduce.Job),设置配置信息 2.通过jobsubmitter将job.xml + sp ...

  9. RMAN备份,catalog注册rman带库备份信息

    客户需求:测试恢复的过程中,控制文件是全备时期的,recover database无法恢复到指定日期,控制文件中缺失后续新的归档备份信息. 方法:1.控制文件rman注册后续带库中的归档备份: 2.使 ...

  10. docker 启动 容器----bootstrap checks failed

    错误信息: bootstrap checks failed 解决方法: 1.修改elasticsearch.yml配置文件,允许外网访问. vim config/elasticsearch.yml,增 ...