热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

webpack4.0优化那些事儿

一削减文件搜刮局限1include&exclude1)action限定编译局限2)useagemodule:{rules:[{test:\.js$,use:[babel-loade

一 削减文件搜刮局限

1 include & exclude

1) action

  • 限定编译局限

2) useage

module: {
rules: [
{
test: /\.js$/,
use: ['babel-loader?cacheDirectory'],
include: path.resolve(__dirname, 'src'),
exclude: /node_modules/
}
]
}

‘babel-loader?cacheDirectory’

You can also speed up babel-loader by as much as 2x by using the cacheDirectory option. This will cache transformations to the filesystem.

QA

命令行warning

[BABEL] Note: The code generator has deoptimised the styling of “/Users/xxx/Documents/xxx/webpack_test/test3/node_modules/lodash/lodash.js” as it exceeds the max of “500KB”.

加上exclude限定局限就不会报错了

2 resolve.modules

1) action

  • Tell webpack what directories should be searched when resolving modules.

2) useage

resolve: {
modules: [path.resolve('node_modules'), path.resolve('lib')]
}

3) note

  • Absolute and relative paths can both be used, but be aware that they will behave a bit differently.
  • A relative path will be scanned similarly to how Node scans for node_modules, by looking through the current directory as well as it’s ancestors (i.e. ./node_modules, ../node_modules, and on).
  • With an absolute path, it will only search in the given directory.
  • If you want to add a directory to search in that takes precedence over node_modules/:(即是有先后顺序的)

modules: [path.resolve(__dirname, "src"), "node_modules"]

4) QA

Module not found: Error: Can’t resolve ‘ajax’ in ‘/Users/xxx/Documents/xxx/webpack_test/test3/src’

当你须要指定除node_modules以外的别的模块目次的时刻可以在数组中增加属性

3 resolve.mainFields

1) action

  • Webpack 设置中的 resolve.mainFields 用于设置第三方模块运用哪一个进口文件。

装置的第三方模块中都邑有一个 package.json文件,用于形貌这个模块的属性,个中有些字段用于形貌进口文件在那里,resolve.mainFields 用于设置采纳哪一个字段作为进口文件的形貌。

可以存在多个字段形貌进口文件的缘由是由于有些模块可以同时用在多个环境中,针对差异的运转环境须要运用差异的代码。 以 isomorphic-fetch API 为例,它是 Promise的一个完成,但可同时用于浏览器和 Node.js 环境。

2) useage

为了削减搜刮步骤,在你明白第三方模块的进口文件形貌字段时,你可以把它设置的只管少。 由于大多数第三方模块都采纳 main字段去形貌进口文件的位置,可以如许设置 Webpack:

module.exports = {
resolve: {
// 只采纳 main 字段作为进口文件形貌字段,以削减搜刮步骤
mainFields: ['main'],
},
};

4 resolve.alias

1) action

  • 设置项经由过程别号来把原导入途径映射成一个新的导入途径
  • 此优化要领会影响运用Tree-Shaking去除无效代码

2) useage

alias: {
"bootstrap": "bootstrap/dist/css/bootstrap.css"
}

5 resolve.extensions

1) action

  • 在导入语句没带文件后缀时,Webpack会自动带上后缀后去尝试讯问文件是不是存在 –
  • 默许后缀是 extensions: [‘.js’, ‘.json’]

2) useage

3) note

  • 后缀列表只管小
  • 频次最高的往前方
  • 导出语句里只管带上后缀

6 module.noParse

1) action

  • module.noParse 设置项可以让 Webpack 疏忽对部份没采纳模块化的文件的递归剖析处置惩罚

2) useage

module: {
noParse: [/react\.min\.js/]
}

2) note

被疏忽掉的文件里不应该包括 import 、 require 、 define 等模块化语句

二 DLL

1 action

dll 为后缀的文件称为动态链接库,在一个动态链接库中可以包括给其他模块挪用的函数和数据

  • 把基础模块自力出来打包到零丁的动态衔接库里
  • 当须要导入的模块在动态衔接库里的时刻,模块不能再次被打包,而是去动态衔接库里猎取

2 usage

定义插件(DLLPlugin) —> 援用插件(DllReferencePlugin)

本次例子用jquery举例

1) 定义DLL

  • 用于打包出一个个动态衔接库
  • 须要零丁build

webpack.jquery.config.js

module.exports = {
entry: ["jquery"],
output: {
filename: "vendor.js",
path: path.resolve(__dirname, "dist"),
libraryTarget: 'var',// 打包的体式格局,hou
library: "vendor_lib_vendor"// DLL的名字
},
plugins: [
new webpack.DllPlugin({
name: "vendor_lib_vendor",// 定义DLL
path: path.resolve(__dirname, "dist/vendor-manifest.json")
})
]
};

package.json 的scripts增加

"dll": "webpack --config webpack.jquery.config.js --mode development"

设置好上述的文件后,在终端运转 npm run dll,时刻会在dist目次下天生两个文件,分别是vendor.jsvendor-manifest.jsonvendor.js包括的就是打包后的jquery文件代码,vendor-manifest.json是用来做关联的。DLL定义好了,接下来就是运用打包好的DLL了。

2) 援用DLL

webpack.config.js 设置文件中引入DllPlugin插件打包好的动态衔接库

plugins: [
new webpack.DllReferencePlugin({
context: __dirname,
manifest: require("./dist/vendor-manifest.json")
})
],

3) 运用DLL

app.html

在app.html的底部增加

3 note

libraryTarget
library

当用 Webpack 去构建一个可以被其他模块导入运用的库时须要用到它们。

  • output.libraryTarget 设置以何种体式格局导出库。
  • output.library 设置导出库的称号。 它们平常搭配在一起运用。

output.libraryTarget 是字符串的罗列范例,支撑以下设置。

1) var (默许)

编写的库将经由过程 var 被赋值给经由过程 library 指定称号的变量。

假如设置了 output.library=’LibraryName’,则输出和运用的代码以下:

// Webpack 输出的代码
var LibraryName = lib_code; //个中 lib_code 代指点出库的代码内容,是有返回值的一个自实行函数。
// 运用库的要领
LibraryName.doSomething();

2) commonjs2

编写的库将经由过程 CommonJS 范例导出。

假如设置了 output.library=’LibraryName’,则输出和运用的代码以下:

// Webpack 输出的代码
exports['LibraryName'] = lib_code;
// 运用库的要领
require('library-name-in-npm')['LibraryName'].doSomething();
// 个中 library-name-in-npm 是指模块宣布到 Npm 代码堆栈时的称号。

3) commonjs2

编写的库将经由过程 CommonJS2 范例导出,输出和运用的代码以下:

// Webpack 输出的代码
module.exports = lib_code;
// 运用库的要领
require('library-name-in-npm').doSomething();

CommonJS2 和 CommonJS 范例很类似,差异在于 CommonJS 只能用 exports 导出,而 CommonJS2 在 CommonJS 的基础上增加了 module.exports 的导出体式格局。
在 output.libraryTarget 为 commonjs2 时,设置 output.library 将没有意义。

4) this

编写的库将经由过程 this 被赋值给经由过程 library 指定的称号,输出和运用的代码以下:

// Webpack 输出的代码
this['LibraryName'] = lib_code;
// 运用库的要领
this.LibraryName.doSomething();

5) window

编写的库将经由过程 window 被赋值给经由过程 library 指定的称号,即把库挂载到 window 上,输出和运用的代码以下:

// Webpack 输出的代码
window['LibraryName'] = lib_code;
// 运用库的要领
window.LibraryName.doSomething();

6) global

编写的库将经由过程 global 被赋值给经由过程 library 指定的称号,即把库挂载到 global 上,输出和运用的代码以下:

// Webpack 输出的代码
global['LibraryName'] = lib_code;
// 运用库的要领
global.LibraryName.doSomething();

三 HappyPack

1 action

HappyPack就能让Webpack把使命剖析给多个子历程去并发的实行,子历程处置惩罚完后再把效果发送给主历程。

2 usage

install

由于webpack 4.0 方才宣布,相应的插件还没有更新完,不过可以在背面加一个@next来装置行将宣布的版本

npm i happypack@next -D

webpack.config.js

module: {
rules: [
{
test: /\.css$/,
use: 'happypack/loader?id=css',
//把对.js文件的处置惩罚转交给id为babel的HappyPack实例
//用唯一的标识符id来代表当前的HappyPack是用来处置惩罚一类特定文件
include: path.resolve('./src'),
exclude: /node_modules/
},
{
test: /\.js/,
use: 'happypack/loader?id=babel',
include: path.resolve('./src'),
exclude: /node_modules/
}
]
},
plugins: [
new HtmlWebPackPlugin({
template: './src/index.html'
}),
new HappyPack({
id: 'babel',
loaders: ['babel-loader']// 和rules里的设置雷同
}),
new HappyPack({
id: 'css',
loaders: ['style-loader', 'css-loader']// 和rules里的设置雷同
}),
]

四 ParallelUglifyPlugin

1.action

  • 可以把对JS文件的串行紧缩变成开启多个子历程并行实行

2 usage

insatll

npm install webpack-parallel-uglify-plugin -D

webpackage.config.js

new ParallelUglifyPlugin({
workerCount: os.cpus().length - 1,//开启几个子历程去并发的实行紧缩。默许是当前运转电脑的 CPU 核数减去1
uglifyJS: {
output: {
beautify: false, //不须要格式化
comments: true, //不保留解释
},
compress: {
warnings: false, // 在UglifyJs删除没有用到的代码时不输出正告
drop_console: true, // 删除一切的 `console` 语句,可以兼容ie浏览器
collapse_vars: true, // 内嵌定义了然则只用到一次的变量
reduce_vars: true, // 提取出涌现屡次然则没有定义成变量去援用的静态值
}
}
})

五 服务器自动革新

1 文件监听

1) action

  • 可以监听文件变化,当文件发生变化的时刻从新编译

2) useage

watch: true,
watchOptions: {
ignored: /node_modules/,
aggregateTimeout: 300,
poll: 1
}

3) note

watch

只要在开启监听形式时(watch为true),watchOptions才有意义

aggregateTimeout

监听到变化发生后等300(ms)再去实行行动,防备文件更新太快致使编译频次太高

poll

经由过程不断的讯问文件是不是改变来推断文件是不是发生变化,默许每秒讯问1000次

文件监听流程

webpack定时猎取文件的更新时候,并跟上次保留的时候举行比对,不一致就示意发生了变化,poll就用来设置每秒问多少次。

当检测文件不再发生变化,会先缓存起来,等守候一段时候后以后再关照监听者,这个守候时候经由过程aggregateTimeout设置。

webpack只会监听entry依靠的文件
我们须要只管削减须要监听的文件数目和搜检频次,固然频次的下落会致使灵敏度下落。

2 自动革新浏览器

1) use

devServer: {
inline: true
},

2) note

webpack担任监听文件变化,webpack-dev-server担任革新浏览器。这些文件会被打包到chunk中,它们会代办客户端向服务器提议WebSocket衔接

3 模块热替代

1) action

  • 模块热替代(Hot Module Replacement)的手艺可在不革新全部网页的情况下只更新指定的模块.
  • 道理是当一个源码发生变化时,只从新编译发生变化的模块,再用新输出的模块替代掉浏览器中对应的老模块

2) 长处

  • 回响反映更快,时候更短
  • 不革新网页可以保留网页运转状况
  • 监听更少的文件
  • 疏忽掉 node_modules 目次下的文件

2) use

webpack.config.js

devServer: {
hot:true//将hot设置为true
},
// 须要的插件
plugins: [
new webpack.NamedModulesPlugin(),//显现模块的相对途径
new webpack.HotModuleReplacementPlugin()// 启动热加载功用
]

code

if (module.hot) {
module.hot.accept('./hot.js', () => {
let hot = require('./hot');
document.getElementById('app2').innerHTML = hot + '1';
})
}

3 note

须要热加载的模块须要在初始化的时刻引入到模块中,不然不会触发HMR。

六 辨别环境

1 action

在开辟网页的时刻,平常都邑有多套运转环境,比方,在开辟过程当中轻易开辟调试的环境。宣布到线上给用户运用的运转环境。

线上的环境和开辟环境区分主要有以下差异:

  • 线上的代码被紧缩
  • 开辟环境可以会打印只要开辟者才看到的日记
  • 开辟环境和线上环境后端数据接口可以差异

2 usage

package.json

  • cross-env跨平台设置环境变量(背面没有&&)

"scripts": {
"build-dev": "cross-env NODE_ENV=development webpack --mode development",
"build-prod": "cross-env NODE_ENV=production webpack --mode production"
}

webpack.config.js

  • 依据环境变量辨别临盆环境照样开辟环境,然后和webpack.base.config.js兼并,临盆环境(或许开辟环境)的优先级高于webpack.base.config.js的设置。

let merge = require('webpack-merge');
let base = require('./webpack.base.config');
let other = null;
if (process.env.NODE_ENV === 'development') {
other = require('./webpack.dev.config');
} else {
other = require('./webapack.prod.config');
}
module.exports = merge(base, other);

webpack.base.config.js

  • 基础设置
  • webpack.DefinePlugin 定义环境变量

基础设置...
plugins: [
new webpack.DefinePlugin({
__isDevelopment__: JSON.stringify(process.env.NODE_ENV == 'development')
})
]

webpack.dev.config.js

  • output举例,假如开辟和临盆环境的参数差异,就会掩盖webpack.base.config.js内里的设置

const path = require('path');
module.exports = {
output: {
path: path.resolve('./dist'),
filename: "[name].dev.[hash:2].js"
}
};

webpack.prod.config.js

  • (以output举例)

const path = require('path');
module.exports = {
output: {
path: path.resolve('./dist'),
filename: "[name].prod.[hash:8].js"
}
};

base.js

  • 设置文件中的webpack.DefinePlugin定义的变量(__isDevelopment__),在进口文件和进口文件援用的其他文件中都可以猎取到__isDevelopment__的值

let env = null;
if (__isDevelopment__) {
env = 'dev';
} else {
env = 'prod';
}
module.exports = env;

index.js

let env = require('./base.js');
if (__isDevelopment__) {
console.log('dev');
} else {
console.log('prod');
}
console.log('env', env);
/*
prod
env prod
*/

3 note

webpack.DefinePlugin

定义环境变量的值时用 JSON.stringify 包裹字符串的缘由是环境变量的值须如果一个由双引号包裹的字符串,而 JSON.stringify(‘production’)的值恰好即是'”production”‘

七 CDN

CDN 又叫内容分发收集,经由过程把资本布置到世界各地,用户在接见时根据就近准绳从离用户近来的服务器猎取资本,从而加快资本的猎取速率。

  • HTML文件不缓存,放在本身的服务器上,封闭本身服务器的缓存,静态资本的URL变成指向CDN服务器的地点
  • 静态的Javascript、CSS、图片等文件开启CDN和缓存,而且文件名带上HASH值
  • 为了并行加载不壅塞,把差异的静态资本分配到差异的CDN服务器上

八 Tree Shaking

1 action

tree Shaking 可以用来剔除Javascript中用不上的死代码。

2 useage

  • 它依靠静态的ES6模块化语法,比方经由过程import和export导入导出
  • 不要编译ES6模块

use: {
loader: 'babel-loader',
query: {
presets: [
[
"env", {
modules: false //寄义是封闭 Babel 的模块转换功用,保留底本的 ES6 模块化语法
}
],
"react"
]
}
},

3 note

须要注重的是它依靠静态的ES6模块化语法,比方经由过程import和export导入导出。也就是说假如项目代码运转在不支撑es6语法的环境上,Tree Shaking也就没有意义了。

九 提取大众代码

1 为何须要提取大众代码

大网站有多个页面,每一个页面由于采纳雷同手艺栈和款式代码,会包括许多大众代码,假如都包括进来会有题目

雷同的资本被反复的加载,糟蹋用户的流量和服务器的本钱;
每一个页面须要加载的资本太大,致使网页首屏加载迟缓,影响用户体验。 假如能把大众代码抽离成零丁文件举行加载能举行优化,可以削减收集传输流量,下落服务器本钱

2 怎样提取

1) 分类

差异范例的文件,打包后的代码块也差异:

  • 基础类库,轻易历久缓存
  • 页面之间的公用代码
  • 各个页面零丁天生文件

2) usage

webpack.config.js

optimization: {
splitChunks: {
cacheGroups: {
commons: {// 页面之间的公用代码
chunks: 'initial',
minChunks: 2,
maxInitialRequests: 5, // The default limit is too small to showcase the effect
minSize: 0 // This is example is too small to create commons chunks
},
vendor: {// 基础类库
chunks: 'initial',
test: /node_modules/,
name: "vendor",
priority: 10,
enforce: true
}
}
}
},

./src/pageA.js

require('./utils/utility1.js');
require('./utils/utility2.js');
require('react');

./src/pageB.js

require('./utils/utility2.js');
require('./utils/utility3.js');

./src/pageC.js

require('./utils/utility2.js');
require('./utils/utility3.js');

utils/utility1.js

module.exports = 1;

utils/utility2.js

module.exports = 2;

utils/utility3.js

module.exports = 3;

打包后的效果

上述三种代码的天生的效果,以下图:
《webpack4.0优化那些事儿》

十 Scope Hoisting

1 action

Scope Hoisting 可以让 Webpack 打包出来的代码文件更小、运转的更快, 它又译作 “作用域提拔”,是在 Webpack3 中新推出的功用。

  • 代码体积更小,由于函数说明语句会发生大批代码
  • 代码在运转时由于建立的函数作用域更少了,内存开支也随之变小 hello.js

2 useage

package.json

"build": "webpack --display-optimization-bailout --mode development",

webpack.config.js

plugins: [
new ModuleConcatenationPlugin()
],

./h.js

export default 'scope hoist'

./index.js

import str from './h.js'
console.log(str);

3 note

必需运用ES6语法,不然不起作用(
--display-optimization-bailout 参数会提醒)

十一 代码星散

代码星散是 webpack 中最有目共睹的特征之一。此特征可以把代码星散到差异的 bundle 中,然后可以按需加载或并行加载这些文件。 有三种经常使用的代码星散要领:

  • 进口出发点:运用 entry 设置手动地星散代码。
  • 防备反复:运用 splitChunks 去重和星散 chunk。
  • 动态导入:经由过程模块的内联函数挪用来星散代码。

进口出发点和防备反复上面已提到了,下面我们重点讲一下动态导入

1 action

用户当前须要用什么功用就只加载这个功用对应的代码,也就是所谓的按需加载 在给单页运用做按需加载优化时,平常采纳以下准绳:

  • 对网站功用举行分别,每一类一个chunk
  • 关于初次翻开页面须要的功用直接加载,尽快展现给用户
  • 某些依靠大批代码的功用点可以按需加载
  • 被支解出去的代码须要一个按需加载的机遇

2 usage

  • 运用import(module)的语法
  • import 异步 加载 模块是一个es7的语法
  • 在webpack里import是一个自然的支解点

document.getElementById('play').addEventListener('click',function(){
import('./vedio.js').then(function(video){
let name = video.getName();
console.log(name);
});
});

参考文档

  • webpack官方文档
  • webpack官方文档中文版
  • webpackGitHub

推荐阅读
  • 本文介绍了前端人员必须知道的三个问题,即前端都做哪些事、前端都需要哪些技术,以及前端的发展阶段。初级阶段包括HTML、CSS、JavaScript和jQuery的基础知识。进阶阶段涵盖了面向对象编程、响应式设计、Ajax、HTML5等新兴技术。高级阶段包括架构基础、模块化开发、预编译和前沿规范等内容。此外,还介绍了一些后端服务,如Node.js。 ... [详细]
  • 本文介绍了高校天文共享平台的开发过程中的思考和规划。该平台旨在为高校学生提供天象预报、科普知识、观测活动、图片分享等功能。文章分析了项目的技术栈选择、网站前端布局、业务流程、数据库结构等方面,并总结了项目存在的问题,如前后端未分离、代码混乱等。作者表示希望通过记录和规划,能够理清思路,进一步完善该平台。 ... [详细]
  • VScode格式化文档换行或不换行的设置方法
    本文介绍了在VScode中设置格式化文档换行或不换行的方法,包括使用插件和修改settings.json文件的内容。详细步骤为:找到settings.json文件,将其中的代码替换为指定的代码。 ... [详细]
  • Webpack5内置处理图片资源的配置方法
    本文介绍了在Webpack5中处理图片资源的配置方法。在Webpack4中,我们需要使用file-loader和url-loader来处理图片资源,但是在Webpack5中,这两个Loader的功能已经被内置到Webpack中,我们只需要简单配置即可实现图片资源的处理。本文还介绍了一些常用的配置方法,如匹配不同类型的图片文件、设置输出路径等。通过本文的学习,读者可以快速掌握Webpack5处理图片资源的方法。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • 本文介绍了Java工具类库Hutool,该工具包封装了对文件、流、加密解密、转码、正则、线程、XML等JDK方法的封装,并提供了各种Util工具类。同时,还介绍了Hutool的组件,包括动态代理、布隆过滤、缓存、定时任务等功能。该工具包可以简化Java代码,提高开发效率。 ... [详细]
  • 如何使用Java获取服务器硬件信息和磁盘负载率
    本文介绍了使用Java编程语言获取服务器硬件信息和磁盘负载率的方法。首先在远程服务器上搭建一个支持服务端语言的HTTP服务,并获取服务器的磁盘信息,并将结果输出。然后在本地使用JS编写一个AJAX脚本,远程请求服务端的程序,得到结果并展示给用户。其中还介绍了如何提取硬盘序列号的方法。 ... [详细]
  • 本文介绍了C++中省略号类型和参数个数不确定函数参数的使用方法,并提供了一个范例。通过宏定义的方式,可以方便地处理不定参数的情况。文章中给出了具体的代码实现,并对代码进行了解释和说明。这对于需要处理不定参数的情况的程序员来说,是一个很有用的参考资料。 ... [详细]
  • 本文介绍了一个程序,可以输出1000内能被3整除且个位数为6的所有整数。程序使用了循环和条件判断语句来筛选符合条件的整数,并将其输出。 ... [详细]
  • 动态规划算法的基本步骤及最长递增子序列问题详解
    本文详细介绍了动态规划算法的基本步骤,包括划分阶段、选择状态、决策和状态转移方程,并以最长递增子序列问题为例进行了详细解析。动态规划算法的有效性依赖于问题本身所具有的最优子结构性质和子问题重叠性质。通过将子问题的解保存在一个表中,在以后尽可能多地利用这些子问题的解,从而提高算法的效率。 ... [详细]
  • Linux环境变量函数getenv、putenv、setenv和unsetenv详解
    本文详细解释了Linux中的环境变量函数getenv、putenv、setenv和unsetenv的用法和功能。通过使用这些函数,可以获取、设置和删除环境变量的值。同时给出了相应的函数原型、参数说明和返回值。通过示例代码演示了如何使用getenv函数获取环境变量的值,并打印出来。 ... [详细]
  • 本文介绍了PE文件结构中的导出表的解析方法,包括获取区段头表、遍历查找所在的区段等步骤。通过该方法可以准确地解析PE文件中的导出表信息。 ... [详细]
  • 3.223.28周学习总结中的贪心作业收获及困惑
    本文是对3.223.28周学习总结中的贪心作业进行总结,作者在解题过程中参考了他人的代码,但前提是要先理解题目并有解题思路。作者分享了自己在贪心作业中的收获,同时提到了一道让他困惑的题目,即input details部分引发的疑惑。 ... [详细]
  • python限制递归次数(python最大公约数递归)
    本文目录一览:1、python为什么要进行递归限制 ... [详细]
  • 本文介绍了如何使用jQuery和AJAX来实现动态更新两个div的方法。通过调用PHP文件并返回JSON字符串,可以将不同的文本分别插入到两个div中,从而实现页面的动态更新。 ... [详细]
author-avatar
肖筱童2502874877
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有