全局安装
npm i webpack -g
npm i webpack-cli -g
本地安装
npm i webpack -D
npm i webpack-cli -D
只执行webpack命令,不配置webpack.config.js文件:
默认编译./src/index.js文件,默认输出./dist/main.js文件
配置
mode
//默认development 开发模式 production 生产模式打包上线
{
mode: "production",
}
entry
{
//字符串写法,只有一个输入口
entry: path.join(__dirname, "../src/index.js"),//输入文件入口
//对象写法,可以有多个输入口
entry:{
index:path.join(__dirname, "../src/index.js"),
main:path.join(__dirname, "../src/main.js"),
}
}
output
{ //文件输出口
output: {
path: path.join(__dirname, '../dist'),
filename: 'js/[name].js',
publicPath: '/',//输出文件起始路径 默认"/"
},
}
filename 配置hash值
// hash 只要整个entry关联的任意一个需要打包的代码发生了变化都会重新生成
// chunkHash 一个入口/一个异步加载的入口关联的的任意一个需要打包的代码发生了变化都会重新生成(关联文件产生hash)
// contentHash 一个入口/一个异步加载的入口关联的的任意一个需要打包的代码发生了变化都会重新生成(文件内容产生hash)
// hash 每次改动都会使其他文件产生新的一致的hash值没有改变过的文件也会产生新的 :8表示生成几位数hash值,
{ //文件输出口
output: {
path: path.join(__dirname, '../dist'),
filename: 'js/[name].[hash:8].js',
publicPath: '/',//输出文件起始路径 默认"/"
},
}
// chunkHash 一个入口/一个异步加载的入口关联的的任意一个需要打包的代码发生了变化都会重新生成(关联文件产生hash)
{ //文件输出口
output: {
path: path.join(__dirname, '../dist'),
filename: 'js/[name].[chunkHash:8].js',
publicPath: '/',//输出文件起始路径 默认"/"
},
}
// contentHash 一个异步加载的入口关联的的任意一个需要打包的代码发生了变化都会重新生成(文件内容产生hash),
{ //文件输出口
output: {
path: path.join(__dirname, '../dist'),
filename: 'js/[name].[contentHash:8].js',
publicPath: '/',//输出文件起始路径 默认"/"
},
}
插件
clean-webpack-plugin 自动删除dist文件
npm i clean-webpack-plugin -D
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
new CleanWebpackPlugin(),//清除文件
html-webpack-plugin html文件打包插件
npm i html-webpack-plugin -D
const HtmlWebpackPlugin = require('html-webpack-plugin')
plugins: [
new HtmlWebpackPlugin({
template: path.join(__dirname, '../static/index.html'),
filename: "index.html",
title: "首页",
// 在这个页面中包含的块,默认情况下会包含
// 提取出来的通用 chunk 和 vendor chunk。
chunks: ['chunk-vendors', 'chunk-common', 'home']
}),
],
copy-webpack-plugin 静态资源文件打包
npm i copy-webpack-plugin -D
const CopyWebpackPlugin = require('copy-webpack-plugin')
plugins: [
new CopyWebpackPlugin({//静态资源文件
patterns: [
{
from: path.join(__dirname, '../assets'),
to: path.join(__dirname, "../dist")
},
]
})
],
HotModuleReplacementPlugin 热启动,配合wepack-dev-server进行生产环境配置
const { HotModuleReplacementPlugin } = require("webpack")
new HotModuleReplacementPlugi()
单页面多页面 配置普通多页面应用
单页面开发:只有一个html文件 的项目,项目中效果如果是切换页面,使用路由切换div实现
多页面开发:项目中效果有多个页面,就有多少个html页面
mode
两种模式:
开发模式 development 打包压缩混淆的代码
生产模式 production
.map文件报错直接显示那个文件哪一行 需要使用 devtool: “source-map” 或者 devtool: “inline-source-map”
devtool: "cheap-module-source-map",
//生成 .map文件
cross-env插件 判断npm 执行的是哪一个命令
npm i cross-env -D
"scripts": {
"build": "cross-env NODE_ENV=development webpack",
"start": "cross-env NODE_ENV=production webpack-dev-server"
},
mode: process.env.NONE_ENV === "development" ? "development" : "production",//开发模式 "production" development
resolve 配置路径别名
resolve: {
//配置路径别名 使用以下字符串开头表示在其配置路径下
alias: {
//一般情况下会使用,~ ! @
'@': path.join(__dirname, "./src"),
'~': path.join(__dirname, "./static"),
'!': path.join(__dirname, "./compontents"),
'react': process.env.NONE_ENV === "development" ? path.join(__dirname, ".node_modules/react/react.main.js") : path.join(__dirname, ".node_modules/react/react.dev.js"),
}
},
解决css编译
安装插件
npm i css-loader style-loader -D
module: {
rules: [
{
test: /\.css$/,//处理css,
use: [
'style-loader',
'css-loader'
]
},
]
}
解决scss文件编译
npm i node-sass sass-loader -D
module: {
rules: [
{
test: /\.scss$/,//处理css,
use: [
'style-loader',//插入页面
'css-loader',//编译css
'scss-loader'//先编译scss文件
]
},
]
}
解决字体图标等文件编译
npm i file-loader -D
module: {
rules: [
{
test: /\.(ttf|woff|woff2|eot|svg)$/,//处理文件
use: [
'file-loader'
]
},
]
}
解决图片编译
npm i url-loader -D
module: {
rules: [
{
test: /\.(png|jpeg|jpg|gif|webp|bmp)$/,//处理图片
use: [
{
loader:"url-loader",
options:{
limit:10240,//超过最大值不转换为base64格式
}
}
]
},
]
}
解决js语法es6转es5
npm i babel-loader -D
npm i @babel/preset-env -D
共三种
一种是全部引入:
npm i @babel/polyfill -S
require('@babel/polyfill')
一种是按需引入:
npm i @babel/runtime -S
npm i @babel/plugin-transform-runtime -D
npm i core-js@3 -S
import "core-js/modules/es.promise";
var a = new Promise();
这种按需引入需要将使用到的es6语法逐个引入,
常用的方法就是第三种 :@babel/core 再引入 core-js@3包
npm i @babel/core -D
npm i core-js@3 -S
配置:
module: {
rules: [
{
test: /\.js$/,//js文件
use: {
options: {
presets: [
"@babel/preset-react",//解析 js jsx语法
[
//预设的名字
"@babel/preset-env",//es6转义
// 该预设的配置项
{
// es6 api的补丁
// false:不解决 usage:用了什么就引入什么 使用的是core-js entry:使用的就是需要手动引入的@babel/polyfill,在编译阶段分析target按需加载target需要的模块
useBuiltIns: 'entry',//usage按需加载 entry全部加载浏览器缺失的语法 默认entry
corejs: 3,
"targets": {//配置兼容到多少版本浏览器
chrome: 59,//
edge: 13,
firefox: 50,
},
}
]
]
}
}
},
]
}
解决jsx语法编译
npm i @babel/preset-react -D
module: {
rules: [
{
test: /\.js$/,//js文件
use: {
options: {
presets: [
"@babel/preset-react",//解析 jsx语法
[
"@babel/preset-env",//es6转义
{
useBuiltIns: 'usage',//usage按需加载 entry全部加载浏览器缺失的语法 默认entry
corejs: 3,
targets: {//配置兼容到多少版本浏览器
chrome: 59,//
edge: 13,
firefox: 50,
},
}
]
]
}
},
exclude: /node_modules/,//配置项解决 usage 无效问题 不编义node_modules文件
include: /src/,//配置项解决 usage 无效问题 只编译编义src的文件
},
]
}
webpack-dev-server 服务器启动
npm i webpack-dev-server -D
devServer: {
open: true,//是否打开浏览器
port: 9000,//端口
contentBase: path.join(__dirname, '../dist'),
https: false,//是否使用https
proxy: {//配置代理
'/api': {
target: 'http://www.baidu.com',
changeOrigin: true,
}
}
}
热更新:
第一步:
devServer: {
open: true,//是否打开浏览器
port: 9000,//端口
contentBase: path.join(__dirname, '../dist'),
https: false,//是否使用https
inline: true,//热更新第一步
hot: true,//热更新第一步
proxy: {
'/api': {
target: 'http://www.baidu.com',
changeOrigin: true,
}
}
}
第二步:
const { HotModuleReplacementPlugin } = require("webpack")
plugins: [
//热启动第二步
new HotModuleReplacementPlugin()
],
第二步:
//输出入口文件执行:
if (module.hot) {//热启动存在
module.hot.accept(() => {
console.log('接收到了热更新.....');
})
}
优化 build
插件
js优化 terser-webpack-plugin
npm i terser-webpack-plugin -D
const TerserWebpackPlugin = require('terser-webpack-plugin')
optimization: {
concatenateModules: true,
minimizer: [
///混淆压缩代码
new TerserWebpackPlugin({
cache: true,//设置缓存
parallel: true,//开启多线程混淆压缩代码
sourceMap: true,//用了source-map必须为true
terserOptions: {//一般不会再配置了
ecma: undefined,//
warnings: false,//没有警告
parse: {},//压缩
compress: {},//合并
mangle: true, // Note `mangle.properties` is `false` by default.
module: false,
output: null,
toplevel: false,
nameCache: null,
ie8: false,//浏览器的支持
keep_classnames: undefined,//保持class
keep_fnames: false,// 保存的名字
safari10: false,//浏览器的支持
}
})
]
}
css优化 mini-css-extract-plugin 打包css代码
npm i mini-css-extract-plugin -D
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
plugins: [
new MiniCssExtractPlugin({//抽离css
filename: "css/[name].css",//css打包后的名字
chunkFilename: 'css/[id].css',//import 动态引入时 id没有配置引入名则以1 2 3 4 5 命名 import(/*webpackChunckName: a*/ './style.css')
}),
],
module: {
rules: [
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,//打包css文件
// 'style-loader',
'css-loader'
]
},
{
test: /\.scss/,
use: [
MiniCssExtractPlugin.loader,
// 'style-loader',
'css-loader',
'sass-loader'
]
},
]
},
css优化插件 optimize-css-assets-webpack-plugin 处理css,将多个相同的css选择器合并 webpack官网没有
const OptimizeCssAssetsAebpackPlugin = require('optimize-css-assets-webpack-plugin')
plugins: [
new MiniCssExtractPlugin({//抽离css
filename: "css/[name].css",//css打包后的名字
chunkFilename: 'css/[id].css',//import 动态引入时 id没有配置引入名则以1 2 3 4 5 命名 import(/*webpackChunckName: a*/ './style.css')
}),
new OptimizeCssAssetsAebpackPlugin({
assetNameRegExp: /\.css/g,//.css文件结尾
cssProcessor: require('cssnano'),//默认会安装cssnano 使用 OptimizeCssAssetsAebpackPlugin调用cssnano
cssProcessorPluginOptions: {
preset: [
"default",
{
discardComments: {
removeAll: true
}
}
]
},
canPrint: true,//
}),
],
thread-loader 多线程打包 使用简单
npm i thread-loader -D
module: {
rules: [
{
test: /\.css$/,
use: ['thread-loader',//优化css
MiniCssExtractPlugin.loader,//打包css文件
// 'style-loader',
'css-loader'
]
},
{
test: /\.scss/,
use: [
'thread-loader',
MiniCssExtractPlugin.loader,
// 'style-loader',
'css-loader',
'sass-loader'
]
},
]
},
happypack 多线程打包
npm i happypack -D
const Happypack = require('happypack')
plugins: [
new Happypack({
threads: 2, //线程数
loaders: [
'thread-loader',
{
loader: 'babel-loader',
options: {
presets: [
["@babel/preset-env"]
]
}
},
]
})
],
module: {
rules: [
{
test: /\.(ttf|woff|woff2|eot|svg)$/,
use: [
'file-loader'
]
},
{
test: /\.(jpg|jpeg|gif|webp|png|bmp)$/,
use: 'happyack/loader?id=img'
},
{
test: /\.js$/,
use: 'happyack/loader?id=js',//id查找
exclude: /node_modules/,//配置项解决 usage 无效问题 不编义node_modules文件
include: /src/,//配置项解决 usage 无效问题 只编译编义src的文件
},
{
test: /\.vue$/,
use:
{
loader: 'vue-loader'
}
}
]
},
js代码分割优化
//优化
optimization: {//只支持import es6模块化,不支持commonjs的变量提示
namedModules: true,
concatenateModules: true,//只支持es6
//1、css代码优化
minimizer: [
///混淆压缩代码
new TerserWebpackPlugin({
cache: true,//设置缓存
parallel: true,//开启多线程混淆压缩代码
sourceMap: true,//用了source-map必须为true
terserOptions: {//一般不会再配置了
ecma: undefined,//
warnings: false,//没有警告
parse: {},//压缩
compress: {},//合并
mangle: true, // Note `mangle.properties` is `false` by default.
module: false,
output: null,
toplevel: false,
nameCache: null,
ie8: false,//浏览器的支持
keep_classnames: undefined,//保持class
keep_fnames: false,// 保存的名字
safari10: false,//浏览器的支持
}
})
],
//2、js代码优化
splitChunks: {
//initial 同步异步都会分割
//async只有异步会打包
//all全部打包
chunks: 'all',// all | async | initial 一般都用all 全部
minSize: 20000,//最小分割字节 超出20000字节 单独打包
maxSize: 1,//最大文件大小
minChunks: 1,
maxAsyncRequests: 30,
maxInitialRequests: 30,
automaticNameDelimiter: '~',//分割文件链接符
// enforceSizeThreshold: 50000,//强制分割/
cacheGroups: {
defaultVendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true,//webpack
}
}
}
}
DllPlugin 动态链路 不需要安装
1、新建 weback.config.dll.js
const path = require('path')
const webpack = require('webpack')
module.exports = {
mode: 'production',
// entry: {
// 'react': ['react', 'react-dom']
// },
entry: {
'vue': ['vue']
},
output: {
path: path.join(__dirname, './dll'),
filename: '[name]_[hash]'
},
plugins: [
new webpack.DllPlugin({
context: __dirname,
name: '[name]_[hash]',
path: path.join(__dirname, 'manifest.json')
})
],
}
2、执行:npm run dll 保存动态链路资源
"scripts": {
"build": "webpack --config=./config/webpack.config.pro.js",
"start": "webpack-dev-server --config=./config/webpack.config.start.js",
"dll": "webpack --config=./config/webpack.config.dll.js"
},
3、打包配置
//使用预编译好的js
new webpack.DllReferencePlugin({
context: path.join(__dirname, './dll'),
manifest: require('./manifest.json')
}),
优化总结:
//1、js代码压缩优化
//2、css代码抽离优化
//3、css代码压缩优化
//4、js代码分割优化
/* 5、打包速度优化:
1、设置resolve.alias,设置resolve.extensions
2、压缩js TerserWebpackPlugin.parallel:true,开启多线程
3、使用多线程执行webpack
1. thread-loader 二者选其一
2. happypack 二者选其一
4、设置动态链路 DllPlugin,预编译
*/
//打包删除没用的代码 tree-shaking 条件是es6的模块化方式才行 ,不讲解