entry
应用程序入口
output
output 属性告诉 webpack 在哪里输出它所创建的 bundles,以及如何命名这些文件,默认值为 ./dist
loader
loader是文件加载器,能够加载资源文件,并对这些文件进行一些处理,诸如编译、压缩等,最终一起打包到指定的文件中
处理一个文件可以使用多个loader,loader的执行顺序和配置中的顺序是相反的,即最后一个loader最先执行,第一个loader最后执行
第一个执行的loader接收源文件内容作为参数,其它loader接收前一个执行的loader的返回值作为参数,最后执行的loader会返回此模块的JavaScript源码
plugin
在webpack运行的生命周期中会广播出许多事件,plugin可以监听这些事件,在合适的时机通过webpack提供的API改变输出结果。
loader和plugin的区别
对于loader,它是一个转换器,将A文件进行编译形成B文件,这里操作的是文件,比如将A.scss转换为A.css,单纯的文件转换过程
plugin是一个扩展器,它丰富了webpack本身,针对是loader结束后,webpack打包的整个过程,它并不直接操作文件,而是基于事件机制工作,会监听webpack打包过程中的某些节点,执行广泛的任务
Webpack优化可以分为优化开发体验和优化输出质量两部分
优化开发体验
1.优化构建速度
1-1 缩小文件搜索范围
在配置 Loader 时通过 include 去缩小命中范围
1-2 动态链接库Dll
为什么给 Web 项目构建接入 动态链接库 的思想后,会大大提升构建速度呢? 原因在于包含大量复用模块的动态链接库只需要编译一次,在之后的构建过程中被动态链接库包含的模块将不会在重新编译,而是直接使用动态链接库中的代码。 由于动态链接库中大多数包含的是常用的第三方模块,例如 react、react-dom,只要不升级这些模块的版本,动态链接库就不用重新编译。
1-3 使用 HappyPack
在整个
Webpack
构建流程中,最耗时的流程可能就是Loader
对文件的转换操作了,因为要转换的文件数据巨多,而且这些转换操作都只能一个个挨着处理。(运行在 Node.js 之上的 Webpack 是单线程模型的)
HappyPack的核心原理就是把这部分任务分解到多个进程去并行处理,从而减少了总的构建时间。
1-4 使用 ParallelUglifyPlugin
ParallelUglifyPlugin会开启多个子进程,把对多个文件的压缩工作分配给多个子进程去完成,每个子进程其实还是通过
UglifyJS
去压缩代码,但是变成了并行执行。 所以ParallelUglifyPlugin
能更快的完成对多个文件的压缩工作。
1-5 使用自动刷新
使用
webpack
模块负责监听文件,webpack-dev-server
模块则负责刷新浏览器。
1-6 开启模块热替换
1-7 externals
照官方文档的解释,如果我们想引用一个库,但是又不想让webpack打包,并且又不影响我们在程序中以CMD、AMD或者window/global全局等方式进行使用,那就可以通过配置Externals。这个功能主要是用在创建一个库的时候用的,但是也可以在我们项目开发中充分使用Externals的方式,我们将这些不需要打包的静态资源从构建逻辑中剔除出去,而使用CDN的方式,去引用它们。
有时我们希望我们通过script引入的库,如用CDN的方式引入的jquery,我们在使用时,依旧用require的方式来使用,但是却不希望webpack将它又编译进文件中
// html中
<script
src="https://code.jquery.com/jquery-3.1.0.js"
integrity="sha256-slogkvB1K3VOkzAI8QITxV3VzpOnkeNVsKvtkYLMjfk="
crossorigin="anonymous">
</script>
// webpack配置如下
module.exports = {
//...
externals: {
jquery: 'jQuery'
}
};
// jsx中引用
import $ from 'jquery';
$('.my-element').animate(/* ... */);
优化输出质量
1.区分环境
2.CDN 加速
3.Tree Shaking可以用来剔除 JavaScript
中用不上的死代码(没用到的代码)。它依赖静态的 ES6 模块化语法,例如通过 import 和 export 导入导出。
webpack 负责对代码进行标记,把 import & export 标记为 3 类:
1.所有 import 标记为 /* harmony import /
2.被使用过的 export 标记为 / harmony export ([type]) /,其中 [type] 和 webpack 内部有关,可能是 binding, immutable 等等。
3.没被使用过的 import 标记为 / unused harmony export [FuncName] */,其中 [FuncName] 为 export 的方法名称,之后在 Uglifyjs (或者其他类似的工具) 步骤进行代码精简,把没用的都删除。
4.提取公共代码
公共使用的是 jQuery 或者 Vue.js 这些体积较大的模块,不利于公共模块的缓存。
所以我们还需要把这些公共的模块提取到一个单独的 bundle 中。Webpack 中实现公共模块提取非常简单,我们只需要在优化配置中开启 splitChunks 功能就可以了,具体配置如下
// ./webpack.config.js
module.exports = {
entry: {
index: './src/index.js',
album: './src/album.js'
},
output: {
filename: '[name].bundle.js' // [name] 是入口名称
},
optimization: {
splitChunks: {
// 自动提取所有公共模块到单独 bundle
chunks: 'all'
}
}
// ... 其他配置
}
5.按需加载
// 路由懒加载
{
path: '/promisedemo',
name: 'PromiseDemo',
component: resolve => require(['../components/PromiseDemo'], resolve)
}
// import动态导入 和 魔法注释
import(/* webpackChunkName: 'posts' */'./posts/posts')
.then(({ default: posts }) => {
mainElement.appendChild(posts())
})
// 组件懒加载:
components: {
historyTab:resolve => {
require(['../../component/historyTab/historyTab.vue'],resolve)
},
},
// webpack提供的require.ensure()
{
path: '/promisedemo',
name: 'PromiseDemo',
component: resolve => require.ensure([], () => resolve(require('../components/PromiseDemo')), 'demo')
},
{
path: '/hello',
name: 'Hello',
// component: Hello
component: resolve => require.ensure([], () => resolve(require('../components/Hello')), 'demo')
}
网友评论