入口,Webpack执行构建的第一步将从Entry开始,可抽象成输入。css
module.exports = {
entry: './path/to/my/entry/file.js'
}
复制代码
module.exports = {
entry: {
one: './path/one.js',
two: './path/two.js'
},
plugins:[
new HtmlWebpackPlugin({
title:'第一个页面',
template: './pages/one.html', // 指定第一个页面的模板
filename: './pages/one.html', // 指定第一个页面打包完成后的文件名
chunks: ['one','two'] // 指定第一个页面要打包进入的js
}),
new HtmlWebpackPlugin({
title:'第二个页面',
template: './pages/two.html', // 指定第二个页面的模板
filename: './pages/two.html', // 指定第二个页面打包完成后的文件名
chunks: ['one','two'] // 指定第二个页面要打包进入的js
}),
]
}
复制代码
网上关于单页面和多页面的优势和缺点都有比较详细的描述,具体须要应用单页面仍是多页面得根据项目的需求来选择。html
通常单页面的配置都有相应的脚手架,好比vue-cli,集成了wp,减小了配置webpack的不少繁琐的工做vue
多页面应用如今没有脚手架,能够进行配置,具体的实例可参考这篇:node
多页面想向单页面实现组件共用和封装,能够参考这篇进行配置,须要引入ejs模板,参考这篇:jquery
juejin.im/post/5a35f6…webpack
模块,在Webpack里一切皆模块,一个模块对应一个文件。Webpack会从配置的Entry开始递归找出全部依赖的模块。 ####配置Loaderweb
test:匹配要进行转换的文件,使用正则表达式来匹配。正则表达式
include: 只包含指定目录的文件进行转换,加快webpack的编译速度。vue-cli
exclude: 排除某个文件的转换,加快编译和搜索速度。
use:对use后面加参数,好比进行缓存和压缩,也能够加快编译的速度。
module:{
rules: [
{
//解析js文件
test: /\.js$/,
// 用babel-loader转换js文件
// ?cacheDirectory表示传给babel-loader的参数,用于缓存babel的编译结果,加快从新编译的速度
use: ['babel-loader?cacheDirectory']
// 只命中src目录里的Js文件,加快webpack的编译速度
include: path.resolve(_dirname,'src')
},
{
//解析Scss文件
test: /\.scss$/,
// 使用一组loader去处理scss文件
// 处理顺序为从后到前,即先交给scss-loader处理,再将结果交给css-loader,最后交给style-loader
use: ['style-loader','css-loader','sass-loader'],
// 排除node_modules目录下的文件
exclude: path.resolve(__dirname,'node_modules')
},
{
// 对非文本文件采用file-loader加载
test: /\.(gif|png|jpe?g|eot|woff|ttf|svg|pdf)$/,
use: ['file-loader']
}
]
}
复制代码
{
test:[
/\.jsx?$/,
/\.tsx?$/
],
include:[
path.resolve(__dirname,'src'),
path.resolve(__dirname,'tests')
],
exclude:[
path.resolve(__dirname, 'node_modiles'),
path.resolve(__dirname, 'bower_modules')
]
}
复制代码
noPaese配置项可让Webpack忽略对部分没采用模块化的文件的递归解析和处理,这样作的好处是能提升构建性能。 缘由是一些库如jQuery,ChartJS庞大又没有采用模块化的标准,让Webpack去解析这些文件既耗时又没有意义。
noParse: /jquery|chartjs/
复制代码
noParse: (content) => {
//content表明一个模块的文件路径
//返回true或false
return /jquery|chartjs/.test(content)
}
复制代码
由于Webpack是以模块化的js文件为入口的,因此内置了对模块化js的解析功能,支持AMD,CommonJS,SystemJS,ES6 parse属性能够更细粒度地配置哪些模块语法被解析,哪些不被解析。
同noParse配置项的区别在于.parser能够精确到语法层面,而noParse只能控制哪些文件不被解析。
parse的使用方法以下:
modele:{
rules:[
test: /\.js$/,
use: ['babel-loader'],
parser: {
amd: false, //禁用AMD
commonjs: false, // 禁用CommonJS
system: false, // 禁用 SystemJS
harmony: false, // 禁用ES6 import/export
requireInclude: false, // 禁用requireInclude
requireEnsure: false, // 禁用requireEnsure
requireContext: false, // 禁用requireContext
browserify: false, // 禁用browserify
requireJs: false // 禁用requirejs
}
]
}
复制代码
模块转换器,用于将模块的原内容按照需求转换成新内容。
Loader的执行顺序是由后到前的。
每Loader均可以经过URL querystring的方式传入参数,例如 css-loader?minimize中的minimize告诉css-loader要开启css压缩。
向loader中传入属性的方式除了能够经过querystring实现,还能够经过object实现。
user:[
'style-loader',{
loader:'css-loader',
options:{
minimize:true
}
}
]
复制代码
use:[
{
loader:'babel-loader',
options:{
cacheDirectory:true
},
// enforce: 'post'的含义是将该loader的执行顺序放到最后
// enforce: 'pre'的含义是将loader的执行顺序放到最前面
}
]
复制代码
拓展插件,在Webpack构建流程中的特定时机注入拓展逻辑。
Plugin的配置很简单,plugins的配置项接受一个数组,数组里的每一项都是一个要使用的Plugin的实例,Plugin须要的参数经过构造函数传入。
const CommonsChunkPlugin = require('webpack/lib/optimize/CommonsChunkPlugin')
module.exports = {
plugins: [
// 全部页面都会用到的公共代码被提取到common代码块中
new CommonsChunkPlugin({
name: 'common',
chunks: ['a','b']
})
]
}
复制代码
const ExtractTextPluginn = require('extract-text-webpack-plugin')
module:{
reules:[
{
textL /\.css$/,
loaders: ExtractTextPlugin.extract({
use:[
'css-loader'
]
}),
}
]
},
plugins: [
new ExtractTextPlugin({
//从.js文件中提取出来的.css文件的名称
filename: `[name]_[contenthash:8].css`
})
]
复制代码
webpack在启动后会从配置的入口模块出发找出全部依赖的模块,resolve配置webpack如何查找模块所对应的文件
resolve.alias配置项经过别名来将原导入路径映射成一个新的导入路径。例如使用一下配置:
resolve:{
alias:{
components: './src/components'
}
}
复制代码
当经过**import Button from 'components/button'**导入时
实际上被alias等价替换成了import Button from './src/components/button'
在导入语句没带文件后缀时,Webpack会自动带上后缀后去尝试访问文件是否存在。
resolve.extensions用于配置在尝试过程当中用到的后缀列表,默认是:
extensionsL ['.js','.json']
复制代码
也就是说,当遇到require('./data')这样的导入语句时,Webpack会先寻找./data.js文件,若是该文件不存在,就去找./data.json文件,若是仍是找不到就报错。
若是resolve.enforceExtension被配置为true,则全部导入语句都必须带文件后缀,例如开启前import './foo'能正常工做,开启后就必须写成**import './foo.js' **
devltool配置Webpack如何生成source map,默认值是false,即不生成source map,若想构建出的代码生成source map以方便调试,则能够这样配置:
module.export = {
devtool: 'source-map'
}
复制代码
开启source-map会方便咱们开发中的调试,方便咱们定位到具体的代码问题,当也会影响一下相关的构建性能问题,全部要作出多配置文件,开发环境配置和生产环境配置
source-map模式下会输出质量最高且最详细的Source Map,这会形成构建速度缓慢,特别是在开发过程当中须要频繁修改时会增长等待时间
在Source-Map模式下会将Source Map暴露,若构建发布到线上的代码的source map暴力,就等同于源码被泄露
为了解决以上两个问题,能够这样作,以下所述
在开发环境下devtool设置成cheap-module-eval-source-map,由于生成这种source map的速度最快,能加速构建。因为在开发环境下不会作代码压缩,因此在source map的即便没有列信息,也不会影响断电调试.
在生产环境下将devtool设置成hidden-source-map,意思是生成最详细的source map,但不会将source map暴露出去。因为生产环境下会作代码压缩,一个js文件只有一行,因此须要列信息。
在生产环境下一般不会将Source Map上传到http服务器让用户获取,而是上传到JavaScript错误收集系统,在错误收集系统上根据Source Map和收集到的JavaScript运行错误队栈,计算出错误所在源码的位置。
不要在生产环境下使用inline模式的Source Map,由于这会使JavaSctipt文件变的很大,并且会泄露源码。
External用来告诉Webpack要构建的代码中使用了哪些不用被打包的模块,也就是说这些模板是外部环境提供的,Webpack在打包时能够忽略它们
经过externals能够告诉Webpack在js运行环境中已经内置了哪些全局变量,不用将这些全局变量打包到代码中而是直接使用它们。
moudle.export = {
externals: {
//将导入语句里的jquery替换成运行环境里的全局变量jQuery
jquery: 'jQuery'
}
}
复制代码
优化开发体验
优化开发体验的目的是提高开发效率,减小每次构建的耗时
1. 优化构建速度
2. 优化使用体验,经过自动化手段完成一些重复的工资哦,让咱们专一于解决问题自己。
复制代码
优化输出质量
呈现用户体验更好的网页,减小首屏加载时间,提高性能流畅度。
1. 缩小文件的搜索范围
2. 优化Loader的配置,经过include去命中 只有哪些文件去处理,经过exclude去去除哪些文件不须要处理,好比node_module
3. 优化resolve.modules配置
resolve.modules用于配置Webpack去哪些目录下寻找第三方模块。
resolve.modelus的默认值是['node_modules']含义是先去当前目录的./node_modules目录下去找咱们想找的模块,若是没找到,就去上一级目录../node_modules中找,再没有就去../../node_modules中找,以此类推
当安装的第三方模块都放在项目根目录的./node_modules目录下时,就没有必要按照默认的方式去一层层的寻找,能够指明存放第三方模块的绝对路径,以减小寻找,配置以下:
module.exports = {
resolve: {
// 使用绝对路径指明第三方模块存放的位置,以减小搜索步骤
// 其中,__dirname表示当前工做目录,也就是项目根目录
modules: [path.resolve(__dirname,'node_modules')]
}
}
4.优化resolve.alias配置,跳过递归解析操做
5.优化resolve.extensions配置减小后缀,后缀要尽量少,提高速度
6.优化noParse配置
复制代码
包含大量复用模块的动态连接库只需被编译一次,在以后的构建过程当中被动态连接库包含的模块将不会被从新编译,而是直接使用动态连接库中的代码。因为动态连接库中大多数包含的是经常使用的第三方模块,例如react,react-dom,因此只要不升级这些模块的版本,动态连接库就不用从新编译。
Webpack已经内置了对动态连接库的支持,须要经过如下两个内置的额插件接入。
运行在Node.js之上的Webpack是单线程模型,Happy Pack将任务分解给多个子进程去并发执行,子进程处理完后再讲结果发送给主进程,因为js是单线程模型,因此想要发挥多核cpu的功能,就只能经过多进程实现,而没法经过多线程实现。
整个Webpack构建流程中,最耗时的流程可能就是loader对文件的转换操做了,由于要转换的文件数据量巨大,并且这些转换操做都只能一个一个地处理。HappyPack的核心原理就是将这部分任务分解到多个进程中去并行处理,从而减小总的构事件。
本来会使用Uglifyjs去一个一个压缩再输出
Paralleuglifyplugin会开启多个子线程,将对多个文件的压缩工做分配给多个子进程完成,每一个子进程其实仍是经过uglify去压缩代码,可是变成了并行执行,因此Paralleuglifyplugin能更快地完成对多个文件的压缩工做
文件监听是发现源码发生变化时,自动从新构建出新的输出文件.
让Webpack开启监听模式,有以下两种方式。
忽略node_modules
module.export = {
watchOptions:{
ignored: /node_modules/
}
}
复制代码
##区分环境 区分开发环境和生产环境,指定对用的不一样调试模式Source Map,是否开启压缩,是否提取公共代码等
相同的资源被重复加载,浪费用户的流量和服务器成本
页面须要加载的资源太大,会致使网页首屏加载缓慢,影响用户体验。
webpackchunkplugin
复制代码
如何按需加载
在为单页应用作按需加载优化时,通常采用如下原则
将整个网站划分红一个个小功能,再按照每一个功能的相关程度将它们分红几类
将每一类合并为一个chunk,按需加载对应的chunk.
不要按需加载用户首次打开网站是须要看到的画面所对应的功能,将其放到执行入口所在的Chunk中,以减小用户能感知的网页加载时间。