设置webpack模式的几种方法
// webpack.config.js
module.exports = (env) => {
return {
mode: env
//....
}
}
以上两种方式只会影响模块内的环境变量(也不会影响plugin、loader内的环境变量)
3. npx cross-env NODE_ENV=development webpack
cross-env用于设置环境变量(兼容windows和mac)
这种方式是设置当前node的环境变量
执行webpack打包
// 1. 使用默认配置
// npm install webpack webpack-cli -D
// npx webpack
// 2. 自定义配置(webpack.config.js)
const path = require('path')
module.exports = {
mode: 'development',
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'build') // 必须是绝对路径
}
}
// npx webpack --config webpack.config.js
webpack创建静态服务 – webpack-dev-server
// npm install webpack-dev-server -D
// 在webpack.config.js中配置devServer
// 开发服务器的配置 -- 使用的是内存中打包后的文件
const devServer = {
port: 3000,
static: { // webpack5使用static,不再使用contentBase
directory: path.join(__dirname, 'build') // 静态文件目录(如果你还有一些没有参与打包的静态文件也需要作为开发服务器的资源被访问,那你就需要额外通过配置“告诉” webpack-dev-server)
},
open: true, // 自动打开页面
compress: true // 启用gzip压缩
}
将js文件引入模板html – html-webpack-plugin
plugins = [
// 把打包后的js文件引入模板html
new HtmlWebpackPlugin({
template: path.resolve(__dirname, 'src/index.html'),
filename: 'index.html',
minify: {
collapseWhitespace: true, // 去掉换行
removeAttributeQuotes: true // 删除双引号
},
hash: true
})
]
解析less – less-loader
解析css – css-loader (解析@import语法)
生成style标签插入模板 – style-loader
module = {
rules: [
{
test: /\.css$/,
use: [
{
loader: 'style-loader',
options: {
insertAt: 'top'
}
},
'css-loader'
]
},
{
test: /\.less$/,
use: [
'style-loader',
'css-loader',
'less-loader'
]
}
]
}
提取css,用link标签引入 – mini-css-extract-plugin
module = {
rules: [
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader, // 使用loader
'css-loader'
]
}
]
}
plugins = [
new MiniCssExtractPlugin({
filename: 'css/main.css' // 输出路径
})
]
postcss autoprefixer – 给css3样式添加前缀
module = {
rules: [
{
test: /\.less/,
use: [
'style-loader',
'css-loader',
'less-loader',
'postcss-loader'
]
}
]
}
// 添加postcss.config.js文件 postcss插件会读取这个文件
module.exports = {
plugins: [
require('autoprefixer')({
overrideBrowserslist: [
'last 10 Chrome versions',
'last 5 Firefox versions',
'Safari >= 6',
'ie> 8'
]
})
]
}
optimize-css-assets-webpack-plugin – 压缩css
const UglifyjsWebpackPlugin = require('uglifyjs-webpack-plugin');
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin')
optimization = {
minimizer: [
new UglifyjsWebpackPlugin({
cache: true,
parallel: true,
sourceMap: true
}),
new OptimizeCssAssetsWebpackPlugin() // 压缩css资源,会导致js资源没有压缩,需要使用uglifyjs压缩js
]
}
ES6转ES5 – babel-loader @babel/core @babel/preset-env
module = {
rules: [
{
test: /\.js$/,
use: [
{
loader: 'babel-loader', // es6 -> es5
options: {
presets: ['@babel/preset-env']
}
}
]
}
]
}
支持更高级的语法 – npm i @babel/plugin-transform-runtime(支持generator等语法) @babel/runtime @babel/polyfill(支持es7及以上语法) @babel/plugin-proposal-decorators(支持类装饰器语法) -D
module = {
rules: [
test: /\.js$/,
use: [
{
loader: 'babel-loader',
options: {
presets: ["@babel/preset-env"],
plugins: [
["@babel/plugin-proposal-decorators", {
legacy: true
}]
"@babel/plugin-transform-runtime"
]
}
}
]
]
}
配置代码校验 – eslint eslint-loader
module = {
rules: [
{
test: /\.js$/,
use: [
{
loader: 'eslint-loader',
options: {
enforce: 'pre' // 优先执行 post 延后执行
}
}
]
}
]
}
module.exports = {
entry: {
index: './src/index.html',
home: './src/home.html'
},
output: {
filename: '[name].[hash:6].js',
path: path.resolve(__dirname, 'dist')
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
filename: 'index.html',
chunks: ['index'] // 表示只引入名称为index的js文件
}),
new HtmlWebpackPlugin({
template: './src/index.html',
filename: 'home.html',
chunks: ['home', 'index'] // 表示引入名称为index和home的js文件
})
]
}
// source-map 会单独生成一个sourcemap文件,出错了会标识当前报错的行和列
// inline-source-map 不会单独生成sourcemap文件,能提示错误代码准确信息和位置
//
// eval-source-map 不会产生单独的文件 但是可以显示行和列
// cheap-module-source-map 不会产生列 但是是一个单独的映射文件
module.exports = {
devtool: 'source-map'
}
module.exports = {
watch: true,
watchOptions: {
poll: 1000, // 每秒检查一次变动(轮询)
aggregateTimeout: 500, // 防抖
ignored: /node_modules/ // 不需要监控node_modules
}
}
webpack插件
// npm i clean-webpack-plugin -D
const CleanWebpackPlugin = require('clean-webpack-plugin');
module.exports = {
plugins: [
new CleanWebpackPlugin('./build') // 打包后的目录
]
}
// npm i copy-webpack-plugin -D
const CopyWebpackPlugin = require('copy-webpack-plugin')
module.exports = {
plugins: [
new CopyWebpackPlugin({
patterns: [
{
from: './doc', // 静态资源目录
to: './' // 打包后的目录(dist)
}
]
})
]
}
const webpack = require('webpack');
module.exports = {
plugins: [
new webpack.BannerPlugin('bannerbanner') // 在打包生成的每个文件最前面添加版权标识(bannerbanner)
]
}
webpack解决跨域
正向代理: 正向代理代理的对象是客户端(翻墙)
反向代理: 反向代理代理的对象是服务端(nginx) 服反客正
module.exports = {
devServer: {
port: 3000,
static: path.join(__dirname, 'build'),
open: true,
compress: true,
// 1.
proxy: {
// 重写并转发给别的服务器
'/api': {
target: 'http://localhost:5000',
pathRewrite: {
'/api':''
}
}
},
// 2. 模拟数据(废弃,使用setupMiddlewares)
onBeforeSetupMiddleware(devServer){
devServer.app.get('/user', (req, res) => {
res.json({
name: 'before'
})
})
}
}
}
const express = require('express');
const webpack = require('webpack');
let middle = require('webpack-dev-middleware'); // npm i webpack-dev-middleware 启动webpack的中间件
const config = require('./webpack.config.js') // 引入webpack配置文件
const compiler = webpack(config)
let app = express();
app.use(middle(compiler))
app.get('/user', (req, res) => {
res.json({
name: 'zwp'
})
})
app.listen(5000)
解析resolve
module.exports = {
resolve: {
extensions: ['.js', '.css', '.json'], // 自动匹配后缀名
alias: {
bootstrap: 'bootstrap/dist/css/bootstrap.css' // 路径别名
},
mainFields: [], // 当从npm包中导入模块时,此选项将决定在 package.json 中使用哪个字段导入模块
mainFiles: [], // 解析目录时要使用的文件名
modules: [path.resolve('node_modules')] // 告诉webpack模块解析时应该搜索的目录
}
}
环境变量
// 内置插件DefinePlugin
const webpack = require('webpack')
module.exports = {
plugins: [
new webpack.DefinePlugin({
DEV: JSON.stringify('development'),
FLAG: 'true',
EXPRESSION: '1+1' // 使用时会执行字符串
})
]
}
// key会作为全局变量属性
// index.js
console.log(DEV) // development
console.log(FLAG) // true
console.log(EXPRESSION) // 2
// webpack.config.base.js
module.exports = {
// 基础配置
}
// webpack.config.prod.js
const {merge} = require('webpack-merge')
const base = require('./webpack.config.js')
module.exports = merge(base, {
mode: 'production'
})
// webpack.config.dev.js
const {merge} = require('webpack-merge')
const base = require('./webpack.config.js')
module.exports = merge(base, {
mode: 'development'
})
webpack优化
module.exports = {
entry: './src/index',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'build')
},
module: {
noParse: /jquery/, // 不解析项目中import的jquery中的依赖库
rules: [
{
test: /\.js$/,
use: {
loader: 'babel-loader',
options: {
presets: [
'@babel/preset-evn',
'@babel/preset-react'
]
}
}
}
]
}
}
module.exports = {
plugins: [
// 正则匹配要忽略的引入的文件路径
new webpack.IgnorePlugin({
resourceRegExp: /(\/locale)/
})
]
}
// webpack.react.js -- 用于打包第三方库
const path = require('path')
const webpack = require('webpack')
module.exports = {
mode: 'production',
entry: {
react: ['react', 'react-dom']
},
output: {
filename: '_dll_[name].js',
path: path.resolve(__dirname,'dist'),
library: '_dll_[name]' // 定义变量名称,将导出的结果赋值给这个变量
// libraryTarget: 'umd' // 模式
},
plugins: [
// 生成清单,可以找到这个动态链接库
new webpack.DllPlugin({
name: '_dll_[name]', // 这里的name要和library保持一致!!
path: path.resolve(__dirname,'dist', 'manifest.json')
})
]
}
// 1. 通过 npx webpack --config webpack.react.js生成打包结果和manifest清单
// 2. 将打包后的js文件手动引入模板index.html文件 <script src="../dist/_dll_react.js"></script>
// 3. 在主项目中通过DllReferencePlugin查找清单
// webpack.config.js
plugins = [
new webpack.DllReferencePlugin({
manifest: path.resolve(__dirname, 'dist', 'manifest.json') // 去动态链接库里查找,找不到再进行打包
})
]
// npm i happypack -D
const HappyPack = require('happypack')
module = {
rules: [
{
test: /\.js$/,
use: 'happypack/loader?id=js'
}
]
}
plugins = [
new HappyPack({
id: 'js',
use: [
{
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env', '@babel/preset-react'],
plugins: [
// ["@babel/plugin-proposal-decorators", {
// "legacy": true
// }],
"@babel/plugin-transform-runtime"
]
}
}
]
})
]
// test.js
export default {
add() {
console.log('add')
}
}
// index.js
const Add = require('./test.js')
Add.default.add() // 'add'
module.exports = {
optimization: {
// 分割代码块
splitChunks: {
// 缓存组
cacheGroups: {
common: {
chunks: 'initial',
minSize: 0,
minChunks: 2 // 有两个以上的引用就抽离出来
},
vendor: {
priority: 1, // 默认是从上到下执行(不设置优先级,会将第三方库和上面的公共代码打包到一起),这个选项设置为优先执行
test: /node_modules/,
minSize: 0,
minChunks: 2
}
}
}
}
}
const button = document.createElement('button')
button.innerHTML = '按钮'
document.body.appendChild(button)
button.addEventListener("click", function () {
import('./source').then(data => {
console.log(data)
})
})
devServer = {
hot: true // 默认开启
}