- Entry 入口文件 指示webpack以哪个文件为起点开始打包,分析构建内依赖图
- Output 输出打包后资源bundles文件地址 及命名
- Loader 处理那些非JavaScript的文件(webpack自身只理解JavaScript
- Pluggins 插件 面向更多强大的功能
- Mode
- 开发环境 development 能让代码本地调试运行的环境
- 生产环境 production 能让代码优化上线运行的环境
结论:
- webpack能处理js/json资源,不能处理css/img等其他资源
- 生产环境及开发环境将ES模块编译成浏览器能识别等模块化
- 生产环境比开发环境多了一个压缩js代码
Entry 入口起点
- string --- './src/index.js'
单入口
打包形成一个chunk,输出一个bundle文件 chunk的默认名称为main
- array --- ['./src/index.js','./src/Block.js']
多入口
所有文件都会打包成一个chunk,输出去的只有一个bundle文件
---只有在HMR功能中让html生效~
- object
多入口
几个文件就打包成几个chunk,输出几个bundle文件
entry: {
index: './src/index.js',
test: './src/test.js'
},
entry: {
index: ["./src/index.js","./src/block.js"], //所有文件最终形成一个文件,输出出去只有一个bundle文件
test: "./src/test.js"
},
output 打包后的文件目录
output: {
//文件名称(指定名称)
filename: 'liang[name].[contenthash:10].js',
//输出的文件目录(所有资源输出的公共目录)
path: path.resolve(__dirname, 'dist'),
//所有资源(引入)公共路径前缀 ---'imgs/a.jpg' --- '/imgs/a.jpg' (一般用于生产环境)
publicPath: '/',
//打包时自动删除上次生成的包
clean: true,
//非入口chunk的命名 如 import 和 optimization打包名称
chunkFilename:'[name]_chunk.js',
//打包后文件的名称默认为main
library:'[name]',
//将打包后的变量名添加到哪个环境上 'global' || 'window' ||'commonjs'
libraryTarget:'window'
},
loader
module: {
rules: [
{
oneOf: [ //以下loader只匹配一个,不能有两个处置处理同一类型的文件,(遇到css less只匹配一个loader)
{
test: /.css$/,
//多个loader用use
use:['style-loader', 'css-loader'] ,
},
{
test: /.(js|jsx)$/,
//排除文件node_module下的js文件
exclude: /(node_modules)/,
//只检查src下面的js文件
include: resolve(__dirname,'src'),
//优先执行'pre' 延迟执行 'post' 不设置顺序执行
enforce:'pre',
},
]
},
]
},
resolve
resolve: {
//配置解析模块路径别名
alias: {
$css: resolve(__dirname, 'src') // src下的文件引用可以设置为 import '$css/index.less';
},
//告诉webpack解析模块是去找哪个目录
modules: [resolve(__dirname,'./node_modules'),'node_modules']
}
devserver
devServer: {
compress: true,//对服务进行gzip 压缩
port: 3001,
hot: true,//开启HMR功能 热更新 1.css style-loader 2.js
proxy:
//一旦devserver服务器接收到/api/xxx的请求,就会把请求转发到另一个服务器(3000)
'/api':target: 'http://localhost:3000',
//发送请求时,请求路径重写,将/api/xxx --- /xxx(去掉/api)
pathRewrite:{'^/api:''}
},
浏览器和服务器之间有跨域,同源策略。
域名 端口 协议
服务器之间没有跨域,浏览器和代理之间没有跨域问题,代理之间没有跨域
代码分割
1.多入口
2.import
3.optimization
const TerserPlugin = require("terser-webpack-plugin");
optimization: { //node_modules依赖单独打包为一个chunk
splitChunks: {
chunks: 'all',
//以下都是默认值
minSize: 30 * 1024, //分割的chunk最小为30kb,
maxSize: 0, // 最大没有限制
minChunks:1,//要提取的chunk最小被引用一次
maxAsyncRequests:5,//按需加载时并行加载的最大文件的最大数量
maxInitialRequests:3, //入口文件最大并行请求数量
......
},
//将当前模块记录其他模块的hash值单独打包为一个文件 runtime
//解决:b文件引入了a文件,修改a文件导致b文件的contenthash值变化,引起缓存失效
runtimeChunk: {
name: (entrypoint) => `runtimechunk~${entrypoint.name}~~~~`,
},
minimize: true,
minimizer: [ //匹配压缩的文件
new TerserPlugin({
test: /.js(?.*)?$/i,
}),
],
},
webpack.config.js webpack的配置文件
作用 :指定webpack干哪些活儿 运行指令时会加载里面的配置
所有构建工具都是基于nodejs 平台运行的~模块化默认采用commonjs
使用方法
loader 1.下载 2.使用(配置loader
plugins 1.下载 2.引用 3.使用(配置plugin
插件
html-webpack-plugin 默认创建空的HTML文件,自动引入打包后的输出的所有资源(CSS/JS资源)
webpack-dev-server 安装内置服务器,用来自动化(自动化编译,自动打开浏览器,自动刷新浏览器
mini-css-extract-plugin 将打包后js中的css代码提取出来
css-minimizer-webpack-plugin css代码压缩
loader
css-loader
html-loader 处理html文件中的img图片
postcss-loader postcss-preset-evn 处理css兼容性
eslint-config-airbnb-base eslint-plugin-import eslint eslint-loader 配置eslint
babel babel-loader @babel/core
@babel/preset-env ****处理基本兼容性
core-js 更多兼容性处理---实现按需加载
兼容IE 模拟js的运行环境 让老版本的浏览器用新版本的环境 可配置按需加载
thread-loader 多进程打包
webpack 代码优化
devtool
- source-map :外部
错误代码准确信息和源代码的错误位置
- inline-source-map:内联
错误代码准确信息和源代码的错误位置
- hidden-source-map :外部
错误代码错误原因,但没有错误位置
不能追踪源代码错误,只能提示构建后代码的错误位置
- eval-source-map:内联
错误代码准确信息和源代码的错误位置
- nosources-source-map : 外部
显示错误代码准确原因 不生成 SourceMap
- cheap-source-map :外部
错误代码准确信息和源代码的错误位置,只能精确到行
inline 代码内通过 dataUrl 形式引入 SourceMap
hidden 生成 SourceMap 文件,但不使用
eval eval(...) 形式执行代码,通过 dataUrl 形式引入 SourceMap 速度最快
nosources 不生成 SourceMap
cheap 只需要定位到行信息,不需要列信息
module 展示源代码中的错误位置
1.开发环境
- 优化打包构建速度
- 优化代码调试
速度快 eval-cheap-source-map eval速度最快,且只需定到行
调试更友好 cheap-module-source-map 错误原因定位到源代码中,报错时精确到行,
最佳 eval-cheap-module-source-map
2.生产环境性能优化 (内联会让代码体积变大,所以在生产下不要用内联
- 优化打包构建速度
- 优化代码运行的性能
nosources-source-map 全部隐藏
hidden-source-map 只隐藏源代码,会提示打包后代码错误信息
source-map none
/**
* 语法检查 eslint-loader eslint
* 注意:只检查自己写的源代码,第三方库不检查
* 设置检查规则
* package.json 中 eslintConfig中设置
* "eslintConfig":{
* "extends":"airbnb-base"
* }
* airbnb ---> eslint-config-airbnb-base eslint-plugin-import eslint
* **/
{
test: /.js$/,
exclude: /node_modules/,
loader: 'eslint-loader',
enforce: 'pre',// loader优先执行
options: {
//自动修复eslint的错误
fix: true
}
},
缓存
babel缓存
cacheDirectory: true
文件资源缓存
- hash:每次webpack构建时会生成唯一的hash值 ,任何一个文件改动,整个项目的构建 hash 值都会改变
filename: 'bundle.[hash:10].js
问题:如果js和css同时使用一个hash值,重新打包会导致所有缓存失效(可能我只改了一个文件却更新了所有文件)
2.chunkhash:根据chunk生成的hash值,如果打包来源于同一个chunk,那么hash值就一样,文件的改动只会影响其所在 chunk 的 hash 值
filename: 'chunkhash.js'
问题:css和js值还是一样的 是因为要在js中引入css
3.contenthash:根据文件内容来生成hash值,不同文件的hash值一定不一样,只会影响自身
filename:'[name].[contenthash:10].js',
\
tree shaking :去除无用代码
前提:
1.必须使用ES6模块化
2.开启 production(生产环境 )生产模式,打包比较慢,会开启 tree-shaking 和压缩代码
// 所有文件都有副作用,全都不可 tree-shaking
{
"sideEffects": true
}
// 没有文件有副作用,全都可以 tree-shaking
{
"sideEffects": false
}
// 只有这些文件有副作用,所有其他文件都可以 tree-shaking,但会保留这些文件
{
"sideEffects": [
"./src/file1.js",
"./src/file2.js"
]
}
{
//test指定的是规则生效的文件
test: /.js$/,
//要使用的loader
use: [
//配置babel 兼容老的浏览器
{
//指定加载器
loader: "babel-loader",
//设置babel
options: {
//设置与定义的环境
presets: [
[
//指定环境的插件
"@babel/preset-env",
//配置信息
{
//兼容的目标浏览器
targets: {
chrome: "60",
ie: "11"
},
//指定corejs的版本
corejs: {
version: 3
}, //比如ie11没有Promise 它会用自己的Promise方法
//使用corejs的方式 "usage"表示按需加载
useBuiltIns: "usage",
modules: false
}
]
],
cacheDirectory: true //生产环境 开启babel缓存 第二次构建时,会读取之前的缓存
}
},
// 'ts-loader' //加载器从后往前执行 先用ts-loader把ts代码转化为js 然后再用babel转换为老版本的js
],
//要排除的文件
exclude: /node_modules/
},
打包
entry: './src/index.js',
entry: {
index:'./src/index.js',
test:'./src/test.js'
},
filename:'[name].[contenthash:10].js',
optimization
1.可以将node_modules的依赖单独打成一个chunk最终输出
2.自动分析多入口chunk中,有无公共的代码,如果有单独打包成一个chunk
optimization: {
splitChunks: {
chunks: 'all'
}
}
/**
通过js代码,让某个文件单独打包成一个chunk
import 动态导入语法:能将某个文件单独打包
**/
import('./test')
.then((result) => {
console.log(result);
})
.catch(() => {
console.log('文件加载失败!');
})
以上代码在index.js中
懒加载&预加载
//懒加载当文件点击时才加载
//正常加载是并行加载,同一个时间加载多个文件
//预加载 Prefetch 会在使用之前提前加载js文件,等其他资源加载完毕,浏览器空闲了,在偷偷加载资源
const add = () => {
return import(/*webpackChunkName: 'test',webpackPrefetch:true*/'./test').then(({ test }) => {
return console.log(test, '00');
});
}
多进程打包 thread-loader
进程启动大概为600ms,进程通信也有开销,大项目才适合多教程打包
tnpm i thread-loader -D
const config = {
//...
{
test: /.(js|jsx)$/,
exclude: /(node_modules|bower_components)/,
use: [
{
loader: 'thread-loader', // 开启多进程打包
options: {
worker: 3,
}
},
{
loader: 'babel-loader',
options: { presets: ['@babel/env', '@babel/preset-react'] },
}
],
},
};
externals 配置选项提供了「从输出的 bundle 中排除依赖」的方法
例如,从 CDN 引入 jQuery,而不是把它打包:
<script
src="https://code.jquery.com/jquery-3.1.0.js"
integrity="sha256-slogkvB1K3VOkzAI8QITxV3VzpOnkeNVsKvtkYLMjfk="
crossorigin="anonymous"
></script>
const config = {
//...
externals: {
jquery: 'jQuery',
},
};
import $ from 'jquery';
$('.my-element').animate(/* ... */);
我们可以用这样的方法来剥离不需要改动的一些依赖,大大节省打包构建的时间。
1.开发环境性能优化
优化打包构建速度
- HRM
-
- css style-loader
- js
if (module.hot) {
module.hot.accept();
}
优化代码调试
- source-map
2 .生产环境性能优化
优化打包构建速度
- oneOf 找到了就直接用 忽略其他loader(需要两个loader处理的时候需要提取出去不呢直接使用
- babel 缓存
{
loader: 'babel-loader',
options: {
presets: ['@babel/env', '@babel/preset-react'],
cacheDirectory: true //开启babel js缓存
},
},
- 多进程打包(进程启动大概为600ms,进程通信也有开销,大项目才适合多教程打包
{
test: /.(js|jsx)$/,
exclude: /(node_modules|bower_components)/,
use: [
{
loader: 'thread-loader', // 开启多进程打包
options: {
worker: 3,
}
},
],
},
优化代码运行的性能
- 缓存(hash-chunkhash-contenthash)
- tree shaking 去除无用代码 sideEffect:["./src/file2.js"]
- code split
单入口 输出一个文件
optimization :node_modules依赖单独打包为一个chunk
多入口 几个入口就输出几个文件
optimization :提取多个入口文件中对node_modules依赖 不会重复打包以依赖
-
- import 制定js文件打成一个包
optimization: { //node_modules依赖单独打包为一个chunk
splitChunks: {
chunks: 'all'
}
},
- 懒加载/预加载
-
- 懒加载 点击的时候再加载
- 预加载 等其他js css文件加载之后悄悄加载 用的时候是缓存
- externals 不打包jquery库 用cdn的方法引用