/**
* 开发环境的配置: 能让代码运行即可
* 整体流程: 源代码 --> webpack(+自动化) --> bundle(输出文件)
*/
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');
const webpack = require('webpack');
const AddAssetHtmlWebpackPlugin = require('add-asset-html-webpack-plugin');
// process.env.NODE_ENV = 'development';
module.exports = {
entry: ['./src/index.js', './src/index.html'],
output: {
filename: 'js/build.js',
path: resolve(__dirname, 'build'),
},
// loader配置
module: {
rules: [
{
// 匹配的文件
test: /\.css$/,
// 使用的loader
// use数组执行顺序从后往前!!!
use: [
// 创建style标签,将js中的样式资源插入进行,添加到head中生效
'style-loader',
// 将css文件变成commonjs模块加载到js中,里面的内容是字符串
'css-loader',
],
},
{
test: /\.less$/,
use: [
// 'style-loader',
MiniCssExtractPlugin.loader,
'css-loader',
// css兼容性处理: postcss --> 安装postcss-loader 和 postcss-preset-env
// postcss-preset-env帮助postcss找到package.json中browserslist里面的配置,通过配置加载指定的css兼容性样式
// browserslist:{
// // 开发环境 --> 设置node环境变量: process.env.NODE_ENV = "development" 可以看development
// "development":[
// "last 1 chrome version",
// "last 1 firefox version",
// "last 1 safari version"
// ],
// // 生产环境: 默认postcss-preset-env是看production
// "production": [
// ">0.2%",
// "not dead",
// "not op_mini all"
// ]
// }
{
loader: 'postcss-loader',
options: {
ident: 'postcss',
plugins: () => [require('postcss-preset-env')()],
},
},
// 将less文件编译成css文件 需要下载 less 和 less-loader两个包
'less-loader',
],
},
{
test: /(\.sass)|(\.scss)$/,
use: [
'style-loader',
'css-loader',
// 将sass文件编译成css文件 需要下载 sass 和 sass-loader两个包
'sass-loader',
],
},
// 处理图片资源
// 默认处理不了html中img标签的图片!!!
{
test: /\.(jpg|png|gif)$/,
// 下载url-loader file-loader (url-loader依赖与file-loader)
loader: 'url-loader',
options: {
// 图片大小小于8Kb就会被base64处理
// 优点: 减少请求数量(减轻服务器压力)
// 缺点:图片体积会更大(文件请求速度更慢)
limit: 8 * 1024,
// [hash:10]表示取图片的hash值前10位
// [ext]表示取文件原来扩展名
name: '[hash:10].[ext]',
// 关闭url-loader的es6模块化,使用commonjs模块化
ESModule: false,
outputPath: 'imgs',
},
},
{
test: /\.html$/,
// 处理html文件的img图片(负责引入img,从而能被url-loader处理)
loader: 'html-loader',
},
// 打包其他资源 (直接生成不需要进行其他操作的文件)
{
exclude: /\.(css|js|less|html|jpg|png|gif)$/,
loader: 'file-loader',
options: {
name: '[hash:10].[ext]',
outputPath: 'media',
},
},
/**
* 语法检查: eslint-loader eslint
注意: 只需要检查源代码,第三方的库不需要检查
设置检查规则:
在package.json 中 eslintConfig中设置
使用airbnb语法规则 --> 安装 eslint-config-airbnb-base eslint-plugin-import eslint
*/
/**
* 当一个文件要被多个loader处理时,一定要指定loader执行的先后顺序
* 先执行eslint,再执行babel
* enforce:'pre'
*/
// {
// test: /\.js$/,
// exclude: /node_modules/,
// loader: 'eslint-loader',
// enforce: 'pre',
// options: {
// fix: true,
// },
// },
// js兼容性处理
// 安装 babel-loader @babel/core @babel/preset-env
/**
* 1. 基本js兼容性处理 --> @babel/preset-env
* problem: 只能转化基本语法,如promise等高级语法不能转换
* 2. 全部js兼容性处理 --> @babel/polyfill (不需要写配置,只需要在入口文件的js文件中引入)
* problem: 只需要解决部分兼容性问题,但是将所有兼容性代码全部引入,体积太大了
* 3. 按需加载js兼容性 --> core-js(需要配合@babel/preset-env使用)
*
*/
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
options: {
// 预设: 指示babel做怎么样的兼容性处理
presets: [
[
'@babel/preset-env',
{
useBuiltIns: 'usage',
corejs: { version: 3 },
targets: {
chrome: '60',
firefox: '60',
ie: '9',
safari: '10',
edge: '17',
},
},
],
],
},
},
],
},
// optimization: {
// splitChunks: {
// chunks: 'all',
// },
// },
// plugins配置
// 使用插件,要先下载,然后引入,最后使用!!
plugins: [
// html-webpack-plugin
// 默认会创建一个空的html,自动引入打包输出的所有资源(JS/CSS)
new HtmlWebpackPlugin({
template: './src/index.html',
// minify: {
// collapseWhitespace: true,
// removeComments: true,
// },
}),
new MiniCssExtractPlugin({
filename: 'css/index.css',
}),
new OptimizeCssAssetsWebpackPlugin(),
new WorkboxWebpackPlugin.GenerateSW({
clientsClaim: true,
skipWaiting: true,
}),
// 告诉webpack这些库不参与打包,同时使用时的名称也得改变
new webpack.DllReferencePlugin({
manifest: resolve(__dirname, 'dll/manifest.json'),
}),
// new AddAssetHtmlWebpackPlugin({
// filepath: resolve(__dirname, 'dll/jquery.js'),
// }),
],
// development特点: 能让代码本地调试运行的环境
// production特点: 能让代码优化上线运行的环境
mode: 'development',
// mode: 'production',
// 开发服务器devServer: 用来自动化(自动编译、自动打开浏览器、自动刷新浏览器)
// 特点: 只会在内存中编译打包,不会有任何输出
// 启动devServer指令: npx webpack-dev-server
// 本地运行的包使用npx, 由于webpack是-g全局安装,所以不需要使用npx
devServer: {
contentBase: resolve(__dirname, 'build'),
watchContentBase: true,
// 如果出错了,不要全屏提示
overlay: false,
// 除了一些基本启动信息外,其他内容不要显示
quiet: true,
// 不要显示启动服务器日志信息
clientLoglevel: 'none',
compress: true,
open: true,
hot: true,
port: 3000,
proxy: {
'/api': {
target: 'http://localhost:3000',
pathRewrite: {
// 发送请求时重写路径,将 /api/xxx --> /xxx (去掉/api)
'^/api': '',
},
},
},
},
devtool: 'source-map',
resolve: {
alias: {
$: resolve(__dirname, 'src'),
},
extensions: ['.json', '.js', '.jsx'],
modules: [resolve(__dirname, 'node_modules'), 'node_modules'],
},
};
// webpack 优化配置
/**
* 1. 开发环境性能优化
* * 优化打包构建速度(HMR --> hot module replacement 热模块替换)
* 作用: 一个模块发生变化,只能重新打包这一个模块(而不是重新打包所有模块)
*
* 样式文件:可以使用HMR功能 --> 因为style-loader内部实现了 (开发环境使用style-loader)
* js文件: 默认不能使用HMR --> 需要修改js代码,添加支持HMR功能的代码
* 注意: HMR功能对js的处理,只能处理非入口js文件
* html文件: 默认不能使用HMR功能,同时会导致html文件不能热更新了(HMTML文件只有一个不需要做HMR功能)
* 解决: 修改entry入口,将html文件引入
*
* * 优化代码调试(source-map)
* source-map: 提供源代码到构建后代码映射的技术(如果构建后代码出错,通过映射可以追踪源代码错误)
* devtool: 'source-map'
*
* source-map: 外部
* 能提示 错误代码准确信息 和 源代码的错误位置
* inline-source-map: 内联(只生成一个内联source-map)
* 能提示 错误代码准确信息 和 源代码的错误位置
* hidden-source-map: 外部
* 能提示 错误代码错误原因,但是没有错误位置,不能追踪到源代码的错误位置,只能提示到构建后代码的错误位置
* eval-source-map: 内联(每一个文件都生成对应的source-map,都在eval)
* 能提示 错误代码准确信息 和 源代码的错误位置
* nosources-source-map: 外部
* 能提示错误代码准确信息,但是没有任何源代码细信息
* cheap-source-map: 外部
* 能提示 错误代码准确信息 和 源代码的错误位置,但是只能精确到行
* cheap-module-source-map: 外部
* 能提示 错误代码准确信息 和 源代码的错误位置
* 内联和外部的区别:1. 外部生成了文件,内联没有;2. 内联构建速度更快
*
* 2. 生产环境性能优化(生产环境不能用HMR功能)
* * 优化打包构建速度
* * 优化代码运行的性能
*/
/**
* oneOf 以下loader只会匹配一个
* 注意: 不能有两个配置处理统一类型文件
*/
/**
* 缓存:
* 1.babel缓存
* cacheDirectory: true 开启babel缓存(第二次构建时,会读取之前的缓存)
*
* 目的:让第二次打包构建速度更快
* 2.资源缓存
* 修改文件名(给文件添加hash值,每次webpack构建时会生成一个唯一hash值)
* 问题:因为js和css同时使用一个hash值,如果只修改js(css文件不变),重新打包,会导致所有缓存失效(css缓存也失效了)
*
* 使用chunkhash:根据chunk生成的hash值(如果打包来源于同一个chunk,那么hash值一样)
* 问题:js和css的hash值还是一样的
* 因为css是在js中被引入的,所以属于同一个chunk
* 使用contenthash:根据文件的内容生成hash值。不同文件hash值一定不一样
*
* 目的:让代码上线运行缓存更好使用
*/
/**
* tree shaking (树摇)
* 前提:
* 1. 必须使用ES6模块化
* 2. 开启production环境
*
* 作用: 去除无用的代码,减少代码体积
*
*
* 在package.json中配置 "sideEffects":false 所有代码都没有副作用(都可以进行tree shaking)
* 问题: 可能会把css / @babel/polyfill 等(有副作用)文件去除
* 方法:"sideEffects";["*.css","*.less"] (标记这些文件为副作用文件,不进行tree shaking)
*/
/**
* code split (代码分割)
* 分为多个文件可以并行加载,提高速度,还可以按需加载
*
* 方式一:
* 多入口:
* entry:{
* index: './src/index.js',
* test: './src/test.js'
* }
*
* output: {
* filename: 'js/[name].[contenthash:10].js'
* }
*
*
* 方式二:
* 1. 可以将node_modules中代码单独打包一个chunk最终输出
* 2. 自动分析多入口chunk中有没有公共的文件,如果有会打包程单独一个chunk
* optimization: {
* splitChunks: {
* chunks: all
* }
* }
*
*
* 方式三:
* 通过js代码,让某个文件被单独打包成一个chunk
* import 动态导入语法:能将某个文件单独打包
* import('./test').then().catch()
*
*/
/**
* 懒加载(lazy load)和预加载(prefetch)
* 懒加载:当文件需要使用时才加载;
* 预加载:会在使用之前,提前加载js文件(兼容性比较差,慎用!)
* 正常加载可以认为是并行加载(同一时间加载多个文件),而预加载是指等其他资源加载完毕等浏览器空闲了再加载
*/
/**
* PWA:渐进式网络开发应用程序(离线可以访问)
* (serviceWork 和 cache) --> 兼容性差
* workbox --> workbox-webpack-plugin
*
* new WorkboxWebpackPlugin
*/
webpack配置
最新推荐文章于 2024-09-05 14:26:45 发布