@TOC
webpack 五个核心概念
-
Entry
- 入口(Entry)指示 webpack 以哪个文件为入口起点开始打包,分析构建内部依赖图
- 单入口 输出一个chunk 和 多入口 输出多个chunk
- 入口(Entry)指示 webpack 以哪个文件为入口起点开始打包,分析构建内部依赖图
-
Output
- 输出(Output)指示 webpack 打包后的资源 bundles 输出到哪里去,以及如何命名。
-
Loader
- Loader 让 webpack 能 够 去 处 理 那 些 非 JavaScript 文 件 (webpack 自 身 只 理 解JavaScript)
-
Plugins
- 插件(Plugins)可以用于执行范围更广的任务。插件的范围包括,从打包优化和压缩,一直到重新定义环境中的变量等。
-
Mode 模式(Mode)指示 webpack 使用相应模式的配置。
| 选项 | 描述 | 特点 |
|---|---|---|
| development | 会将 DefinePlugin 中 process.env.NODE_ENV 的值设置为 development。启用 NamedChunksPlugin 和NamedModulesPlugin。 | 能让代码本地调试运行的环境 |
| production | 会将 DefinePlugin 中 process.env.NODE_ENV 的值设置为 production。启用 FlagDependencyUsagePlugin, FlagIncludedChunksPlugin, ModuleConcatenationPlugin, NoEmitOnErrorsPlugin, OccurrenceOrderPlugin, SideEffectsFlagPlugin 和 TerserPlugin。 | 能让代码优化上线运行的环境 |
初始化配
- 初始化 package.json
- 输入指令: npm ini
- 下载并安装 webpack
npm install webpack@4.41.6 webpack-cli@3.3.11 -gnpm install webpack@4.41.6 webpack-cli@3.3.11 -D- 最新版本问题:会造成中突导致运行失败 可运行版本:
npm i webpack@4.16.5 webpack-cli@3.1.0 html-webpack-plugin@3.2.0
编译打包应用命令
- 开发环境指令:
webpack src/js/index.js -o build/js/built.js --mode=development- 功能:webpack 能够编译打包 js 和 json 文件,并且能将 es6 的模块化语法转换成浏览器能识别的语法。
- 生产环境指令:
webpack src/js/index.js -o build/js/built.js --mode=production- 功能:在开发配置功能上多一个功能,压缩代码。
- 结论 webpack 能够编译打包 js 和 json 文件。能将 es6 的模块化语法转换成浏览器能识别的语法。能压缩代码。
- 问题 不能编译打包 css、img 等文件。不能将 js 的 es6 基本语法转化为 es5 以下语法。 需要插件 Loader
Loader下载
- css的loader
style-loader-- 把封装的css只要以style标签引入css-loader-- 打包css资源less-loader-- 解析less变为css 配置less使用mini-css-extract-plugin-- 把css独立封装出来optimize-css-assets-webpack-plugin-- 压缩css资源postcss-loader@3.0.0&postcss-preset-env处理css的兼容性,需要在package.json里配置东西
- HTML和图片等其它资源的loader
url-loader-- 可以用来处理css的图片资源,不可以处理HTML图片html-loader||html-withimg-loader-- 处理HTML的图片file-loader-- 处理文字图标等资源html-webpack-plugin-- 处理 HTML 的
- js的loader
eslint-loader&eslint&eslint-config-airbnb-base&eslint-plugin-import-- 检测 js 语法 需要在package.json配置东西babel-loader&@babel/core&core-js&babel-- 处理 js 兼容性问题- 基本js兼容性处理 -->
@babel/preset-env-- 问题:只能转换基本语法,如promise高级语法不能转换 - 全部js兼容性处理 ->
@babel/polyfill-问题:只解决部分兼容性问题,但是将所有兼容性代码全部引入,体积太大了 - 需要做兼容性处理的就做:按需加载 -->
core-js
webpack-dev-server-- 开发模式插件在module.exports添加target: 'web'// webpack5 bug 不能自动刷新 解决方案
webpack初体验
/*
index.js webpack 入口起点文件
1. 运行指令
开发环境 : webpack ./src/index.js -o ./build/built.js --mode=development
webpack 会义 ./src/index.js 为入口文件,打包后输出到 ./build/built.js
整体打包环境,是开发环境
生产环境 : webpack ./src/index.js -o ./build/built.js --mode=production
整体打包环境,生产环境
2. 结论
1. webpack 能处理js、json文件,不能处理css/img 等其它资源
2. 生产环境和开发环境将 ES6 模块化编译成浏览器能识别的代码
3. 生产环境比开发环境多一个压缩js代码
*/
import data from "./data.json"
// import "./index.css"
console.log(data);
function add (x,y) {
return x + y ;
}
console.log(add(1,3));
webpack 文件打包配置
/*
webpack.config.js webpack配置文件
作用: 指示webpack 干那些活(当你运行 webpack 指令时,会加载里面的配置)
所有构建工具都是基于 nodejs 平台运行大的~模块化默认采用commonjs。
*/
// resolve 用来并接绝对路径的方法
const { resolve } = require('path');
module.exports = {
// webpack 配置
// 入口起点
entry : './src/index.js',
// 输出
output : {
// 输出 文件名
filename : 'built.js',
// 输出路径
// __dirname nodejs的变量,代表当前文件的目录绝对路径
path : resolve(__dirname,'build')
},
// loader 配置
module: {
rules : [
// 详细的loader配置 不同的文件需要不同的loader 处理
{
// 匹配那些文件 正则表达式
test: /\.css$/,
// 使用那些loader进行处理
use: [
// use 数组中loader执行顺序: 从右到左,从上到下 依次执行
// 创建style标签,将js中的样式资源插入进行,添加到head中生效
'style-loader',
// 将css文件将commonjs模块加载到js中,里面的内容是样式字符串
'css-loader'
]
},
{
test: /\.less$/,
use: [
'style-loader',
'css-loader',
'less-loader' // 将 less文件 编译成css文件 需要 less 和 less-loader
]
}
]
},
// plugins(插件) 配置
plugins: [
],
// mode 模式的设置
mode : 'development' // 开发模式
// mode : 'production' // 生产模式
}
打包HTML资源
/*
loader : 1. 下载 2. 使用(配置loader)
plugins : 1. 下载 2. 引入 3. 使用
*/
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin'); // html-webpack-plugin 下载后引入
module.exports = {
entry: './src/index.js',
output: {
filename: 'built.js',
path: resolve(__dirname,'build')
},
module : {
rules: [
// loader 配置
]
},
plugins: [
// 配置plugins nodejs下载 : html-webpack-plugin
// 功能 : 默认会创建一个空的HTML文件,自动引入打包输出的所有资源(js/css)
// 需求 : 需要有结构的
new HtmlWebpackPlugin({
// 复制 "./src/index.html" 文件。并自动引入打包输出的所有资源(js/css)
template: "./src/index.html"
})
],
mode: 'development'
}
打包图片资源
const {resolve} = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
entry: './src/index.js',
output: {
filename: "built.js",
path: resolve(__dirname,'build')
},
module: {
rules: [
{
test: /\.less$/,
// 要使用多个loader处理use
use: ['style-loader','css-loader','less-loader']
},
{
// 问题:默认处理不了HTML的img图片
// 处理图片资源 单个直接使用 loader 不用 use | 处理依赖 url-loader file-loader
test: /\.(jpg|png|gif)$/,
loader: "url-loader",
options: {
// 图片大小小于 8kb 就会被base64处理
// 优点: 减小请求数量(减轻服务器压力) 缺点:图片体积会更大(文件请求速度更慢)
limit: 8* 1024,
// 问题: 因为url-loader默认使用es6模块化解析,而html-loader引入图片时commonjs
// 解析时会出问题: 关闭url-loader的es6模块化,使用commonjs解析 就可以解决了
esModule : false,
// 给图片进行重命名 [hash:10].[ext] 取前十位保持原有的扩展名
name : "[hash:10].[ext]"
}
},
{
test: /\.html$/,
// 处理 HTML文件的图片图片 (负责引入img,从而能被(url-loader/url-withimg-loader)进行处理)
// 当 url-loader 处理不来图片时可以 使用 html-withimg-loader
// loader: " url-loader " 处理不了
loader: "html-withimg-loader"
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: "./src/index.html"
})
],
mode: "development"
}
其它资源打包(字体图标等)
const {resolve} = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry:'./src/index.js',
output: {
filename: "built.js",
path: resolve(__dirname,'build')
},
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader','css-loader']
},
// 如何打包自他资源(除了html/css/js资源以外的资源)
{
// 排除css/js/html资源
exclude: /\.(css|js|html|less)$/,
loader: "file-loader",
options : {
name: "[hash:10].[ext]"
}
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: "./src/index.html"
})
],
mode: "development"
}
derServer 帮助服务器开发
const {resolve} = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry:'./src/index.js',
output: {
filename: "built.js",
path: resolve(__dirname,'build')
},
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader','css-loader']
},
{
// 打包自他资源(除了html/css/js资源以外的资源)
exclude: /\.(css|js|html|less)$/,
loader: "file-loader",
options : {
name: "[hash:10].[ext]"
}
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: "./src/index.html"
})
],
mode: "development",
// 开发服务器 devServer :用来自动化(自动化编译,自动打开浏览器,自动刷新浏览器)
// 特点:只会在内存中编译打包,不会有任何输出 启动 devServer 指令为 : npx webpack-dev-server
// 因为依赖问题最新版的webpack-cli没有 所以需要版本为: "webpack-cli": "^3.3.11"
devServer: {
contentBase: resolve(__dirname, 'build'), // 项目构建后路径
compress: true, // 启动gzip压缩
port: 3000, // 端口号
open: true // 自动打开浏览器
}
}
综合练习
/*
开发环境配置 :让代码运行
运行项目的指令:
webpack 会将打包结果输出
npx webpack-dev-server 只会在内存中编译打包不会输出结果
*/
const {resolve} = require("path");
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/js/index.js',
output: {
filename: "js/built.js",
path: resolve(__dirname,'build')
},
module: {
rules: [
{
test: /\.css$/, // 处理css资源
use: ['style-loader','css-loader']
},
{
test: /\.less$/, // 处理less资源
use: ['style-loader','css-loader','less-loader']
},
{
test: /\.(jpg|png|gif)/, // 处理图片资源
loader: 'url-loader',
options: {
limit: 8 * 1024,
name: '[hash:10].[ext]',
esModule: false, // 关闭es6模块化的解析
outputPath: 'imgs'
}
},
{
test: /.html$/, // 处理HTML的img图片
loader: 'html-withimg-loader',
},
{
exclude: /\.(css|js|html|jpg|less|png|gif)$/, // 处理其它资源(如字体图等)
loader: "file-loader",
options: {
name: '[hash:10].[ext]]',
outputPath: 'media'
}
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: "./src/index.html"
})
],
mode: 'development',
devServer: {
contentBase: resolve(__dirname,'build'),
compress: true,
port: 30000,
open: true
}
}
css文件单独提取
const {resolve} = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
// mini-css-extract-plugin 拆分css文件独立
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
entry: './src/js/index.js',
output: {
filename: "js/built.js",
path: resolve(__dirname,'build')
},
module: {
rules: [
{
test: /\.css$/,
use: [
// 创建一个style标签将样式放入
// 'style-loader',
// 这个loader的作用是取代style-loader来单独提取css文件
MiniCssExtractPlugin.loader,
// 将css文件整合到js文件中
'css-loader'
]
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: "./src/index.html"
}),
new MiniCssExtractPlugin({
// 对输出的文件重命名 并创建文件夹
filename: 'css/built.css'
})
],
mode: 'development'
}
css兼容性处理
const { resolve } = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
// mini-css-extract-plugin 拆分css文件独立
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
// 设置nodejs环境变量
// process.env.NODE_ENV = "development";
module.exports = {
entry: './src/js/index.js',
output: {
filename: "js/built.js",
path: resolve(__dirname,'build')
},
module: {
rules: [
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
/*
css兼容性处理 postcss --> postcss-loader@3.0.0 postcss-preset-env
帮postcss找到package.json中browserslist里面的配置,通过配置加载指定的css兼容性样式
"browserslist": {
// 开发环境 --》 设置node环境变量 : process.env.NODE_ENV = "development"
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version",
"last 1 IE version"
],
// 生产环境 : 默认是看生产环境
"production": [
">0.2%",
"not dead",
"not op_mini all"
]
}
*/
// 使用默认配置 loader : 'postcss-loader'
// 修改loader配置
{
loader: "postcss-loader",
options: {
ident: 'postcss',
plugins: () => [
require("postcss-preset-env")
]
}
}
]
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: "./src/index.html"
}),
new MiniCssExtractPlugin({
filename: 'css/built.css'
})
],
mode: 'development'
}
css 压缩
const { resolve } = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
// mini-css-extract-plugin 拆分css文件独立
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
// 设置nodejs环境变量
// process.env.NODE_ENV = "development";
const OptimizeCssAssetsWebpackPlugin = require("optimize-css-assets-webpack-plugin");
// optimize-css-assets-webpack-plugin 压缩css的插件
module.exports = {
entry: './src/js/index.js',
output: {
filename: "js/built.js",
path: resolve(__dirname,'build')
},
module: {
rules: [
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
{
loader: "postcss-loader",
options: {
ident: 'postcss',
plugins: () => [
require("postcss-preset-env")()
]
}
}
]
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: "./src/index.html"
}),
new MiniCssExtractPlugin({
filename: 'css/built.css'
}),
new OptimizeCssAssetsWebpackPlugin()
],
mode: 'development'
}
js语法检测
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/js/index.js',
output: {
filename: 'js/built.js',
path: resolve(__dirname, 'build'),
},
module: {
rules: [
{
/*
语法检测 : 统一代码样式 使用的插件 : eslint-loader eslint
注意:只检测自己写的源代码,第三方的库是不用检测的
设置检测规则:
package.json中eslintConfig中设置
"eslintConfig" : {
"extends": "airbnb-base"
}
airbnb --》 eslint-config-airbnb-base eslint eslint-plugin-import
*/
test: /\.js$/,
exclude: /node_modules/,
loader: 'eslint-loader',
options: {
// 自动修复错误
fix: true,
},
},
],
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
}),
],
mode: 'development',
};
js兼容性处理
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/js/index.js',
output: {
filename: 'js/built.js',
path: resolve(__dirname, 'build'),
},
module: {
rules: [
/*
js的兼容性处理 : babel-loader @babel/core @babel/preset-env
1. @babel/preset-env : 处理js基本兼容性问题
问题:只能转换基本语法,如promise不能转换
2. 全部js的兼容性处理 : @babel/polyfill
问题: 只要解决部分兼容性问题,但是将所有的兼容性代码全部引入,体积太大
3. 需要做兼容性处理的就做:按需加载 --》 core-js
*/
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/,
options : {
// 预设: 指示babel做怎么样的兼容性处理
// presets: ['@babel/preset-env']
presets: [
[
'@babel/preset-env',
{
// 按需加载
useBuiltIns: 'usage',
// 指定 corejs 的版本
corejs: {
version: 3
},
// 指定兼容性做到哪个版本的浏览器
targets : {
chrome : "60",
firefox: "50",
ie: "9",
safari: "10",
edge: "17",
}
}
]
]
}
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
}),
],
mode: 'development',
};
js & html压缩
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/js/index.js',
output: {
filename: 'js/built.js',
path: resolve(__dirname, 'build'),
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
// 压缩HTML配置
minify: {
// 移除空格
collapseWhitespace: true,
// 移除注释
removeComments: true
}
}),
],
mode: 'production', // 开启 production 自动压缩js
};
生产环境配置
const { resolve } = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const OptimizeCssAssetsWebpackPlugin = require("optimize-css-assets-webpack-plugin");
module.exports = {
entry: './src/js/index.js',
output: {
filename: 'js/built.js',
path: resolve(__dirname,'build')
},
module: {
rules: [
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
{
// 在package.json 配置文件
loader: 'postcss-loader',
options: {
ident: 'postcss',
plugins: () => [
require("postcss-preset-env")()
]
}
}
]
},
{
test: /\.less$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
{
// 在package.json 配置文件
loader: 'postcss-loader',
options: {
ident: 'postcss',
plugins: () => [
require("postcss-preset-env")()
]
}
},
'less-loader'
]
},
/*
正常讲:一个文件只能被一个loader处理
当一个文件要被多个loader处理,那么一定要指定loader执行的先后顺序 先执行 eslint 再 babel
*/
{
// 在package.json中配置eslintConfig --》 airbnb
test: /\.js$/,
exclude: /node_modules/,
enforce: 'pre',
loader: 'eslint-loader',
options: {
fix: true
}
},
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
options: {
presets: [
[
'@babel/preset-env',
{
useBuiltIns: 'usage',
corejs: {version: 3},
targets: {
chrome: "60",
ie: "8",
firefox: "60"
}
}
]
]
}
},
{
test: /\.(jpg|png|gif)/,
loader: 'url-loader',
options: {
limit: 8 * 1024,
name: '[hash:10].[ext]',
esModule: false,
outputPath: 'imgs'
}
},
{
test: /\.html$/,
loader: 'html-withimg-loader',
options: {
outputPath: 'imgs'
}
},
{
exclude: /\.(js|css|less|html|jpg|png|gif)/,
loader: 'file-loader',
options: {
outputPath: 'media'
}
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html'
}),
new MiniCssExtractPlugin({
filename: 'css/built.css'
}),
new OptimizeCssAssetsWebpackPlugin()
],
mode: 'production'
}
HMR 热模块替换(更新修改文件)
/*
HMR:hot module replacement 热模块替换 、 模块热替换 (修改部分更新)
作用:一个模块发生变化。只会重新打包这一个模块(而不是打包所有的模块) 极大提升构建速度
样式文件 : 可以使用HMR功能 : 因为style-loader内部实现了
js文件 :默认不使用 HMR -> 需要修改 js 代码
注意:HMR功能对 js 的处理,只能处理非入口文件的其他文件
HTML文件 :默认不使用HMR功能。同时会导致问题: HTML不能热更新!(不需要做HMR功能)
方案: 修改 entry 入口 将 HTML文件引入 (解决热更新)
*/
const { resolve } = require("path");
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
// target: process.env.NODE_ENV === 'development' ? 'web' : 'browserslist',
target: 'web', // webpack5 bug 不能自动刷新 解决方案
entry: ['./src/js/index.js', './src/index.html'],
output: {
filename: "js/built.js",
path: resolve(__dirname,'build')
},
module: {
rules: [
{
test: /\.css$/, // 处理css资源
use: ['style-loader','css-loader']
},
{
test: /\.less$/, // 处理less资源
use: ['style-loader','css-loader','less-loader']
},
{
test: /\.(jpg|png|gif)/, // 处理图片资源
loader: 'url-loader',
options: {
limit: 8 * 1024,
name: '[hash:10].[ext]',
esModule: false, // 关闭es6模块化的解析
outputPath: 'imgs'
}
},
{
test: /\.html$/, // 处理HTML的img图片
loader: 'html-withimg-loader',
},
{
exclude: /\.(css|js|html|jpg|less|png|gif)$/, // 处理其它资源(如字体图等)
loader: "file-loader",
options: {
name: '[hash:10].[ext]]',
outputPath: 'media'
}
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: "./src/index.html"
})
],
mode: 'development',
devServer: {
contentBase: resolve(__dirname,'build'),
compress: true,
port: 12345,
open: true,
// 开启 HMR 功能 修改配置重启服务
hot: true
}
}
source-map 压缩后代码映射源代码
const { resolve } = require("path");
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
// target: process.env.NODE_ENV === 'development' ? 'web' : 'browserslist',
target: 'web', // webpack5 bug 不能自动刷新 解决方案
entry: ['./src/js/index.js', './src/index.html'],
output: {
filename: "js/built.js",
path: resolve(__dirname,'build')
},
module: {
rules: [
{
test: /\.css$/, // 处理css资源
use: ['style-loader','css-loader']
},
{
test: /\.less$/, // 处理less资源
use: ['style-loader','css-loader','less-loader']
},
{
test: /\.(jpg|png|gif)/, // 处理图片资源
loader: 'url-loader',
options: {
limit: 8 * 1024,
name: '[hash:10].[ext]',
esModule: false, // 关闭es6模块化的解析
outputPath: 'imgs'
}
},
{
test: /\.html$/, // 处理HTML的img图片
loader: 'html-withimg-loader',
},
{
exclude: /\.(css|js|html|jpg|less|png|gif)$/, // 处理其它资源(如字体图等)
loader: "file-loader",
options: {
name: '[hash:10].[ext]]',
outputPath: 'media'
}
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: "./src/index.html"
})
],
mode: 'development',
devServer: {
contentBase: resolve(__dirname,'build'),
compress: true,
port: 12345,
open: true,
hot: true
},
devtool: 'eval-source-map'
}
/*
source-map:一种提供源代码到构建后代码映射技术 (如果构建后代码出错了,通过映射可以追踪到源代码的错误)
[inline-|hidden-|eval-] [nosources-] [cheap-[module]] source-map
source-map : 外部
错误代码的准确信息 和 源代码的错误位置
inline-source-map : 内联
1. 只生成一个 内联 source-map
错误代码的准确信息 和 源代码的错误位置
hidden-source-map : 外部 防泄露
错误代码的错误原因 但是没有错误的位置 不能追踪源代码错误,只能提示到构建后代码的位置
eval-source-map : 内部
1. 每一个文件都生成对应的source-map ,都在 eval
错误代码的准确信息 和 源代码的错误位置 hash值
nosources-source-map : 外部 防泄漏
错误代码的准确信息 但是没有任何源代码信息
cheap-source-map : 外部
错误代码的准确信息 和 源代码的错误位置
只能精确到行
cheap-module-source-map : 外部
错误代码的准确信息 和 源代码的错误位置
module会将loader和source-map加入
内联 和 外部 的区别 :1. 外部生成文件,内联没有 2. 内联构建速度快
开发环境: 速度快,调试更友好
速度快(eval > inline > cheap)
eval-cheap-source-map
eval-source-map
调试更友好 :source-map > cheap-module-source-map > cheap-source-map
--> eval-source-map / eval-cheap-module-source-map
生产环境 :源代码要不要隐藏?调试要不要更友好
内联会让代码的体积变大 所以在生产环境不同内联
nosources-source-map 全部隐藏
hidden-source-map 只隐藏源代码,会提示构建后的代码错误
--> source-map 、 cheap-module-source-map
*/
oneOf
const { resolve } = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const OptimizeCssAssetsWebpackPlugin = require("optimize-css-assets-webpack-plugin");
const CssLoader = [
MiniCssExtractPlugin.loader,
'css-loader',
{
// 在package.json 配置文件
loader: 'postcss-loader',
options: {
ident: 'postcss',
plugins: () => [
require("postcss-preset-env")()
]
}
}
]
module.exports = {
entry: './src/js/index.js',
output: {
filename: 'js/built.js',
path: resolve(__dirname,'build')
},
module: {
rules: [
{
// 在package.json中配置eslintConfig --》 airbnb
test: /\.js$/,
exclude: /node_modules/,
enforce: 'pre',
loader: 'eslint-loader',
options: {
fix: true
}
},
{
// 一下loader只会匹配一次
// 注意: 不能有两项配置处理同一种类型文件
oneOf: [
{
test: /\.css$/,
use: [...CssLoader]
},
{
test: /\.less$/,
use: [ ...CssLoader, 'less-loader']
},
/*
正常讲:一个文件只能被一个loader处理
当一个文件要被多个loader处理,那么一定要指定loader执行的先后顺序 先执行 eslint 再 babel
*/
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
options: {
presets: [
[
'@babel/preset-env',
{
useBuiltIns: 'usage',
corejs: {version: 3},
targets: {
chrome: "60",
ie: "8",
firefox: "60"
}
}
]
]
}
},
{
test: /\.(jpg|png|gif)/,
loader: 'url-loader',
options: {
limit: 8 * 1024,
name: '[hash:10].[ext]',
esModule: false,
outputPath: 'imgs'
}
},
{
test: /\.html$/,
loader: 'html-withimg-loader',
options: {
outputPath: 'imgs'
}
},
{
exclude: /\.(js|css|less|html|jpg|png|gif)/,
loader: 'file-loader',
options: {
outputPath: 'media'
}
}
]
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html'
}),
new MiniCssExtractPlugin({
filename: 'css/built.css'
}),
new OptimizeCssAssetsWebpackPlugin()
],
mode: 'production'
}
缓存babel
const { resolve } = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const OptimizeCssAssetsWebpackPlugin = require("optimize-css-assets-webpack-plugin");
/*
缓存:
babel缓存
cacheDirectory: true
--> 让第二次打包构建速度更快
文件资源缓存
hash: 每次webpack构建时会生成一个唯一的hash值
问题: 因为js和css同时使用一个hash值。如果重新打包会导致所有缓存失效。(可能只改动一个文件)
chunkhash: 根据chunk生成的hash值。如果打包来源于同一个chunk,那么hash值一样
问题: js 和 css 的hash值还是一样的
因为css 是在 js 中被引入的,所以同属于一个chunk
contenthash : 根据文件的内容生成hash值,不同的文件的hash值一定不一样
--> 让代码上线运行缓存更好使用
*/
const CssLoader = [
MiniCssExtractPlugin.loader,
'css-loader',
{
// 在package.json 配置文件
loader: 'postcss-loader',
options: {
ident: 'postcss',
plugins: () => [
require("postcss-preset-env")()
]
}
}
]
module.exports = {
entry: './src/js/index.js',
output: {
filename: 'js/built.[contenthash:10].js',
path: resolve(__dirname,'build')
},
module: {
rules: [
{
// 在package.json中配置eslintConfig --》 airbnb
test: /\.js$/,
exclude: /node_modules/,
enforce: 'pre',
loader: 'eslint-loader',
options: {
fix: true
}
},
{
// 一下loader只会匹配一次
// 注意: 不能有两项配置处理同一种类型文件
oneOf: [
{
test: /\.css$/,
use: [...CssLoader]
},
{
test: /\.less$/,
use: [ ...CssLoader, 'less-loader']
},
/*
正常讲:一个文件只能被一个loader处理
当一个文件要被多个loader处理,那么一定要指定loader执行的先后顺序 先执行 eslint 再 babel
*/
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
options: {
presets: [
[
'@babel/preset-env',
{
useBuiltIns: 'usage',
corejs: {version: 3},
targets: {
chrome: "60",
ie: "8",
firefox: "60"
}
}
]
],
// 开启 babel缓存 第二次构建是会去读取之前的缓存
cacheDirectory: true
}
},
{
test: /\.(jpg|png|gif)/,
loader: 'url-loader',
options: {
limit: 8 * 1024,
name: '[hash:10].[ext]',
esModule: false,
outputPath: 'imgs'
}
},
{
test: /\.html$/,
loader: 'html-withimg-loader',
options: {
outputPath: 'imgs'
}
},
{
exclude: /\.(js|css|less|html|jpg|png|gif)/,
loader: 'file-loader',
options: {
outputPath: 'media'
}
}
]
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html'
}),
new MiniCssExtractPlugin({
filename: 'css/built.[contenthash:10].css'
}),
new OptimizeCssAssetsWebpackPlugin()
],
mode: 'production',
devtool: "source-map"
}
tree shaking
const { resolve } = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const OptimizeCssAssetsWebpackPlugin = require("optimize-css-assets-webpack-plugin");
/*
tree shaking : 去除无用代码
前提: 1. 必须使用 ES6 模块化 2. 开启 production 环境
作用: 减小代码的体积
在package.json中配置
"sideEffects" : false 所有的代码都没有副作用(都可以进行 tree shaking)
问题:可能会把 css 、 @babel/polyfill (副作用)文件干掉
*/
const CssLoader = [
MiniCssExtractPlugin.loader,
'css-loader',
{
// 在package.json 配置文件
loader: 'postcss-loader',
options: {
ident: 'postcss',
plugins: () => [
require("postcss-preset-env")()
]
}
}
]
module.exports = {
entry: './src/js/index.js',
output: {
filename: 'js/built.[contenthash:10].js',
path: resolve(__dirname,'build')
},
module: {
rules: [
{
// 在package.json中配置eslintConfig --》 airbnb
test: /\.js$/,
exclude: /node_modules/,
enforce: 'pre',
loader: 'eslint-loader',
options: {
fix: true
}
},
{
// 一下loader只会匹配一次
// 注意: 不能有两项配置处理同一种类型文件
oneOf: [
{
test: /\.css$/,
use: [...CssLoader]
},
{
test: /\.less$/,
use: [ ...CssLoader, 'less-loader']
},
/*
正常讲:一个文件只能被一个loader处理
当一个文件要被多个loader处理,那么一定要指定loader执行的先后顺序 先执行 eslint 再 babel
*/
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
options: {
presets: [
[
'@babel/preset-env',
{
useBuiltIns: 'usage',
corejs: {version: 3},
targets: {
chrome: "60",
ie: "8",
firefox: "60"
}
}
]
],
// 开启 babel缓存 第二次构建是会去读取之前的缓存
cacheDirectory: true
}
},
{
test: /\.(jpg|png|gif)/,
loader: 'url-loader',
options: {
limit: 8 * 1024,
name: '[hash:10].[ext]',
esModule: false,
outputPath: 'imgs'
}
},
{
test: /\.html$/,
loader: 'html-withimg-loader',
options: {
outputPath: 'imgs'
}
},
{
exclude: /\.(js|css|less|html|jpg|png|gif)/,
loader: 'file-loader',
options: {
outputPath: 'media'
}
}
]
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html'
}),
new MiniCssExtractPlugin({
filename: 'css/built.[contenthash:10].css'
}),
new OptimizeCssAssetsWebpackPlugin()
],
mode: 'production',
devtool: "source-map"
}
code split 代码分隔
demo1
const { resolve } = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
// entry : './src/js/index.js' // 单入口文件
entry: {
// 多入口: 有一个入口,最终输出就有一个 budle
index : './src/js/index.js',
test: './src/js/test.js'
},
output: {
// 取文件名 [name]
filename: 'js/[name].[contenthash:10].js',
path: resolve(__dirname,'build')
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html'
})
],
mode: 'production',
}
demo2
const { resolve } = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
// entry : './src/js/index.js', // 单入口文件
entry: {
index: './src/js/index.js',
test: './src/js/test.js'
},
output: {
// 取文件名 [name]
filename: 'js/[name].[contenthash:10].js',
path: resolve(__dirname,'build')
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html'
})
],
/*
1. 可以将node_modules中的代码单独打包一个chunk最终输出
2. 自动分析多入口chunk中。有没有公共的文件。如有就会打包成一个单独的chunk
*/
optimization: {
splitChunks: {
chunks : "all"
}
},
mode: 'production',
}
demo3
const { resolve } = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
entry : './src/js/index.js', // 单入口文件
output: {
// 取文件名 [name]
filename: 'js/[name].[contenthash:10].js',
path: resolve(__dirname,'build')
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html'
})
],
/*
1. 可以将node_modules中的代码单独打包一个chunk最终输出
2. 自动分析多入口chunk中。有没有公共的文件。如有就会打包成一个单独的chunk
*/
optimization: {
splitChunks: {
chunks : "all"
}
},
mode: 'production',
}
lazy loding 懒加载
webpack.config.js:
const { resolve } = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
entry : './src/js/index.js', // 单入口文件
output: {
// 取文件名 [name]
filename: 'js/[name].[contenthash:10].js',
path: resolve(__dirname,'build')
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html'
})
],
/*
1. 可以将node_modules中的代码单独打包一个chunk最终输出
2. 自动分析多入口chunk中。有没有公共的文件。如有就会打包成一个单独的chunk
*/
optimization: {
splitChunks: {
chunks : "all"
}
},
mode: 'production',
}
js:
console.log("index.js被加载了!");
// import {mul} from "./test"
document.getElementById('btn').onclick = function() { //按钮点击触发
// 懒加载~:当文件需要使用时才加载~
// 预加载 prefetch:会在使用之前,提前加载js文件
// 正常加载可以认为是并行加载(同一时间加载多个文件)
// 预加载 prefetch:等其他资源加载完毕,浏览器空闲了,再偷偷加载资源
import(/* webpackChunkName: 'test', webpackPrefetch: true*/'./test').then(({ mul }) => {
console.log(mul(4, 5));
});
};
pwa离线加载
webpack.config.js:
const { resolve } = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const OptimizeCssAssetsWebpackPlugin = require("optimize-css-assets-webpack-plugin");
const WorkboxWebpackPlugin = require("workbox-webpack-plugin");
/*
PWA: 渐进式网络开发应用程序(离线可访问)
workbox --> workbox-webpack-plugin
*/
const CssLoader = [
MiniCssExtractPlugin.loader,
'css-loader',
{
// 在package.json 配置文件
loader: 'postcss-loader',
options: {
ident: 'postcss',
plugins: () => [
require("postcss-preset-env")()
]
}
}
]
module.exports = {
entry: './src/js/index.js',
output: {
filename: 'js/built.[contenthash:10].js',
path: resolve(__dirname,'build')
},
module: {
rules: [
{
// 在package.json中配置eslintConfig --》 airbnb
test: /\.js$/,
exclude: /node_modules/,
enforce: 'pre',
loader: 'eslint-loader',
options: {
fix: true
}
},
{
// 一下loader只会匹配一次
// 注意: 不能有两项配置处理同一种类型文件
oneOf: [
{
test: /\.css$/,
use: [...CssLoader]
},
{
test: /\.less$/,
use: [ ...CssLoader, 'less-loader']
},
/*
正常讲:一个文件只能被一个loader处理
当一个文件要被多个loader处理,那么一定要指定loader执行的先后顺序 先执行 eslint 再 babel
*/
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
options: {
presets: [
[
'@babel/preset-env',
{
useBuiltIns: 'usage',
corejs: {version: 3},
targets: {
chrome: "60",
ie: "8",
firefox: "60"
}
}
]
],
// 开启 babel缓存 第二次构建是会去读取之前的缓存
cacheDirectory: true
}
},
{
test: /\.(jpg|png|gif)/,
loader: 'url-loader',
options: {
limit: 8 * 1024,
name: '[hash:10].[ext]',
esModule: false,
outputPath: 'imgs'
}
},
{
test: /\.html$/,
loader: 'html-withimg-loader',
options: {
outputPath: 'imgs'
}
},
{
exclude: /\.(js|css|less|html|jpg|png|gif)/,
loader: 'file-loader',
options: {
outputPath: 'media'
}
}
]
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html'
}),
new MiniCssExtractPlugin({
filename: 'css/built.[contenthash:10].css'
}),
new OptimizeCssAssetsWebpackPlugin(),
new WorkboxWebpackPlugin.GenerateSW({
/*
1. 帮助 serviceworker 快速启动
2. 删除旧的 serviceworker
生成一个serviceworker 配置文件
*/
clientsClaim: true,
skipWaiting: true
})
],
mode: 'production',
devtool: "source-map"
}
js:
import '../css/box.css';
import '../css/index.css';
import '../css/iconfont.css';
import { mul } from './test';
function sum(...args) {
return args.reduce((p, c) => p + c, 0);
}
/*
1. eslint 不认识 window ,navigation 全局变量
解决: 需要修改package.json 中的 eslintConfig配置
"env": {
"browser": true // 支持浏览器端全局变量 node:true
}
2. sw 代码必须运行在服务器上
--> nodejs
--> npm i serve -g
serve -s build 启动服务器,将build目录下的所有的资源作为静态资源暴露出去
*/
// eslint-disable-next-line
console.log(mul(2,3));
// eslint-disable-next-line
console.log(sum(1,2,3,4));
// 注册 serviceWorker 处理兼容问题
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('/service-worker.js').then(() => {
console.log('sw注册成功~');
}).catch(() => {
console.log('sw注册失败了~');
});
});
}
多线程
const { resolve } = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const OptimizeCssAssetsWebpackPlugin = require("optimize-css-assets-webpack-plugin");
const WorkboxWebpackPlugin = require("workbox-webpack-plugin");
/*
PWA: 渐进式网络开发应用程序(离线可访问)
workbox --> workbox-webpack-plugin
*/
/*
thread-loader
*/
const CssLoader = [
MiniCssExtractPlugin.loader,
'css-loader',
{
// 在package.json 配置文件
loader: 'postcss-loader',
options: {
ident: 'postcss',
plugins: () => [
require("postcss-preset-env")()
]
}
}
]
module.exports = {
entry: './src/js/index.js',
output: {
filename: 'js/built.[contenthash:10].js',
path: resolve(__dirname,'build')
},
module: {
rules: [
{
// 在package.json中配置eslintConfig --》 airbnb
test: /\.js$/,
exclude: /node_modules/,
enforce: 'pre',
loader: 'eslint-loader',
options: {
fix: true
}
},
{
// 一下loader只会匹配一次
// 注意: 不能有两项配置处理同一种类型文件
oneOf: [
{
test: /\.css$/,
use: [...CssLoader]
},
{
test: /\.less$/,
use: [ ...CssLoader, 'less-loader']
},
/*
正常讲:一个文件只能被一个loader处理
当一个文件要被多个loader处理,那么一定要指定loader执行的先后顺序 先执行 eslint 再 babel
*/
{
test: /\.js$/,
exclude: /node_modules/,
use: [
/*
开启多线程打包
进程启动大概为600ms,进程通信也有开销。只有工作消耗时间较长,才需要多进程打包
*/
{
loader : 'thread-loader',
options : {
Workers : 2 // 进程 2 个
}
},
{
loader: 'babel-loader',
options: {
presets: [
[
'@babel/preset-env',
{
useBuiltIns: 'usage',
corejs: {version: 3},
targets: {
chrome: "60",
ie: "8",
firefox: "60"
}
}
]
],
// 开启 babel缓存 第二次构建是会去读取之前的缓存
cacheDirectory: true
}
}
]
},
{
test: /\.(jpg|png|gif)/,
loader: 'url-loader',
options: {
limit: 8 * 1024,
name: '[hash:10].[ext]',
esModule: false,
outputPath: 'imgs'
}
},
{
test: /\.html$/,
loader: 'html-withimg-loader',
options: {
outputPath: 'imgs'
}
},
{
exclude: /\.(js|css|less|html|jpg|png|gif)/,
loader: 'file-loader',
options: {
outputPath: 'media'
}
}
]
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html'
}),
new MiniCssExtractPlugin({
filename: 'css/built.[contenthash:10].css'
}),
new OptimizeCssAssetsWebpackPlugin(),
new WorkboxWebpackPlugin.GenerateSW({
/*
1. 帮助 serviceworker 快速启动
2. 删除旧的 serviceworker
生成一个serviceworker 配置文件
*/
clientsClaim: true,
skipWaiting: true
})
],
mode: 'production',
devtool: "source-map"
}