webpack配置
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 webpack = require('webpack');
// process.env.NODE_ENV = 'development';
module.exports = {
mode: 'development', //生产模式下会自动压缩js代码
/**
* entry: 入口起点
* 1.string ---》 './src/index.js'
* 单入口
* 打包形成一个chunk,输出一个bundle文件
* 此时chunk的名称默认是main
* 2.array ---》 ['./src/index.js', './src/add.js']
* 多个入口
* 所有文件最终只会形成一个chunk,输出去只有一个bundle文件。
* 3.ojbect
* 多入口
* 有几个入口文件就形成几个chunk,输出几个bundle文件
* 此时的chunk的名称是key
*/
entry: {
index: './src/js/index.js',
},
/**
* 文件名称
* filename: 'js/[name].js'
* 输出文件目录
* path: resolve(__dirname, 'build')
* 所有资源引入的公共路径前缀
* publicPath: '/'
* 非入口chunk的名称
* chunkFilename: 'js/[name]_chunk.js'
* 整个库向外暴露的变量名
* library: '[name]'
* 变量名添加到哪里
* libraryTarget: 'window' //global
*/
output: {
filename: 'js/[name].[contenthash:10].js',
path: resolve(__dirname, 'build'),
publicPath: './',
},
module: {
// js兼容性处理:babel-loader @babel/core
/**
1.基本js兼容处理 --》 @babel/preset-env
问题:只能转换基本语法,如promise不能转换
2.全部js兼容性处理 --》@babel/polyfill
直接在js文件中引入,问题是我只需要解决部分兼容性问题,但是将所有兼容代码引入到文件中,文件体积过大
3.按需加载 --》core-js
*/
rules: [
{
//一下loader只会匹配一个
//注意:不能又两个配置同时处理一个类型文件,这样只会有先匹配的生效,
//解决办法是将另外一个loader移到oneOf外面
oneOf: [
{
test: /.js/,
exclude: /node_modules/,
use: [
/**
* 开启多进程打包
* 进程启动时间大概为600ms,进程通信也有开销
* 只有工作消耗比较长,才需要多进程打包
*/
// 'thread-loader',
{
loader: 'babel-loader',
options: {
presets: [
[
'@babel/preset-env',
{
// 按需加载
useBuiltIns: 'usage',
// 指定core-js版本
corejs: {
version: 3,
},
// 指定兼容到浏览器的哪一个版本
targets: {
browsers: ['last 2 versions'],
},
},
],
],
// 开启babel缓存,第二次构建时,会读取之前的缓存
cacheDirectory: true,
},
},
],
},
{
test: /\.css$/,
// use: ['style-loader', 'css-loader'],
use: [
{
//作用:提取js中的css到单独的css文件
loader: MiniCssExtractplugin.loader,
options: {
publicPath: '../',
},
},
'css-loader',
//css兼容性处理 --->postcss-loader postcss-preset-env
// 通过package.json中browserslist或者.browserslistrc文件配置加载指定的css兼容样式
// "browserslist": {
//默认为生产环境,若想为开发环境需通过precess.env.NODE_ENV = 'development'来配置
// "development": [
// "last 1 chrome version",
// "last 1 firefox version",
// "last 1 safari version"
// ],
// "production": [
// ">0.1%",
// "not dead"
// ]
// }
{
loader: 'postcss-loader',
options: {
ident: 'postcss',
plugins: () => [require('postcss-preset-env')()],
},
},
],
},
{
test: /\.less$/,
//使用多个loader处理用use,否则可用loader
// style-loader:创建style标签,将js中的样式资源插入后添加到head标签中生效
// css-loader:将css文件变成commonjs模块加载到js中,里面内容是样式字符串
// less-loader:将less文件编译成css文件交给css-loader处理
// use: ['style-loader', 'css-loader', 'less-loader'],
use: [
{
//作用:提取js中的css到单独的css文件
loader: MiniCssExtractplugin.loader,
options: {
publicPath: '../',
},
},
'css-loader',
{
loader: 'postcss-loader',
options: {
ident: 'postcss',
plugins: () => [require('postcss-preset-env')()],
},
},
'less-loader',
],
},
{
// 处理图片资源
// 问题:默认处理不了html中的img图片,需使用html-loader来处理
test: /\.(jpeg|jpg|png)$/,
// 使用url-loader需下载url-loader和file-loader,url-loader依赖于file-loader
loader: 'url-loader',
options: {
// 图片大小小于8kb就会被base64处理
// 优点:减少请求数量(减轻服务器压力)
// 缺点:图片体积会更大(文件请求速度更慢)
limit: 8 * 1024,
// 解决:关闭url-loader的es6模块化,使用commonjs解析
esModule: false,
// 给图片重命名
// [hash:10]取图片hash值的前10位
// [ext]取文件原来的扩展名
name: '[hash:10].[ext]',
// 指定处理完成后的输出路径
outputPath: 'image',
},
},
{
test: /\.html$/,
// 处理html文件中的img图片,负责引入img,从而能被url-loader处理
loader: 'html-loader',
},
{
// 打包其他资源(除了html,js,css,less,jpeg等资源)
exclude: /\.(html|js|css|less|jpeg|png|gif|jpg)$/,
loader: 'file-loader',
options: {
name: '[hash:10].[ext]',
outputPath: 'media',
},
},
],
},
],
},
plugins: [
// html-webpack-plugin
// 功能:默认会创建一个空的html,自动引入打包输出的所有资源(js/css)
new HtmlWebpackPlugin({
// 复制'./src/index.html'文件,并自动引入打包输出的所有资源
template: resolve(__dirname, '/src/index.html'),
// outputPath: 'build',
// 压缩html
minify: {
// 移除空格
collapseWhitespace: true,
// 移除注释
removeComments: true,
},
}),
// 将css打包到单独文件
new MiniCssExtractplugin({
filename: 'css/index.[contenthash:10].css',
}),
// 压缩css
new OptimizeCssAssetsWebpackPlugin(),
],
// 开发服务器devServer,用来自动化(自动编译,自动打开浏览器,自动刷新浏览器)
// 特点:只会在内存中编译打包,不会有任何输出
// 启动devServer指令为npx webpack-dev-server
// 现在运行不了是因为包的版本问题
devServer: {
// 项目构建后的路径
contentBase: resolve(__dirname, 'build'),
// 启动gzip压缩
compress: true,
open: true,
port: 3001,
/*
HMR: hot module replacement 热模块替换
作用:一个模块发生变化,只会重新打包这一个模块,而不是打包所有模块,极大提升构建速度
样式文件:可以使用HMR功能,因为style-loader内部实现了
js文件:默认不能使用HMR功能 --》需要修改js代码,添加支持HMR功能的代码
注意:HMR功能对js的处理,只能处理非入口js文件的其他文件。
if (moudle.hot) {
一旦module.hot为true,说明开启了HMR功能
module.hot.accept('./utils.js', function() {
方法会监听utils.js文件的变化,一旦发生变化,其他默认不会重新构建打包
会执行后面的回调函数
})
}
html文件:默认不能使用HMR功能,同时会导致问题:html文件不能热更新,及修改html文件后,页面不会修改
解决:修改entry入口,将html文件引入
entry: ['./src/js/index.js', './src/index.html']
*/
hot: true,
//不要提示启动服务器日志信息
clientLogLevel: 'none',
//吃了一些基本启动信息以外,其他内容都不要提示
quiet: true,
//如果出错了不要全屏提示
overlay: false,
//服务器代理
proxy: {
'/api': {
target: 'http://abc.com',
//发送请求时,请求路径重写 将/api/xxx ---> /xxx
pathRewrite: {
'^/api': '',
},
},
},
},
// 一种提供源代码到构建后代码映射的技术(如果构建后代码出错,通过映射可以追踪源代码错误位置
// [inline-|hidden-|eval-][nosources-][cheap-[module-]]source-map
/**
* source-map:外部(生成一个新的文件)
* 展示错误代码准确信息 和 源代码的错误位置
* inline-source-map: 内联
* 只生成一个内联source-map,展示错误代码准确信息 和 源代码的错误位置
* hidden-source-map:外部
* 错误代码原因,但是没有错误位置,不能追踪源代码错误,只能提示到构建后代码的错误位置
* eval-source-map:内联
* 每一个文件都生成对应的source-map,展示错误代码准确信息 和 源代码的错误位置
* 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
*/
devtool: 'source-map',
/**
* code split 代码分割
* 以下配置可以将node_modules中代码单独打包一个chunk最终输出
* 例如多个入口文件中都引入jquery,不加这个配置则最终输入的出口文件每一个文件中都会引入jquery造成冗余
*
* 在js文件中使用‘import()’引入文件,则引入的文件会被单独打包成一个文件
* ‘import('./index.js').then(() => {})’
*/
// import(/* webpackChunkName: 'test' */'./index.js') /* */里面的内容会重命名打包后的文件
optimization: {
splitChunks: {
chunks: 'all',
},
},
externals: {
//拒绝node_modules中指定的包被打包到输出文件中,需要手动在html文件中引入对应的cdn链接
jquery: 'jQuery',
},
//解析模块的规则
resolve: {
//配置解析模块路径别名: 优点简写路径 缺点路径没有提示
alias: {
'@': resolve(__dirname, 'src'),
},
//配置省略文件路径的后缀名
extensions: ['.js', '.json', '.jsx'],
//告诉webpack解析模块去找哪一个目录
modules: [resolve(__dirname, '../../node_modules'), 'de_modules'],
},
};
/**
* 缓存
* babel缓存
* cacheDirectory: true
* --->让第二次打包构建速度更快
* 文件资源缓存
* hash:每次webpack构建时都会生成一个唯一的hash值
* 问题:因为js和css同时使用同一个hash值,如果重新打包,会导致所有缓存失效(可能我只变更了一个文件)
* chunkhash: 根据chunk(代码块)生成的hash。如果打包源来自同一个chunk,那么hash值就一样
* 问题:js和css的hash值还是一样的,因为css是在js中引入的
* contenthash:根据文件的内容生成hash值,不同文件hash值一定不一样
* --->让代码上线运行缓存更好使用
*/
/**
* tree shaking:去除无用代码
* 前提:1.必须使用es6模块化 2.开启production环境
* 作用:减少代码体积
*
* 在package.json中配置
* "sideEffects":false //所有代码都可以进行tree shaking
* 问题:可能会把css文件干掉
* "sideEffects":["*.css"]排除这些文件不进行tree shaking
*/
/**
* 懒加载和预加载
* 懒加载:当文件需要使用是才加载,使用import().then(() => {})实现
* 预加载prefetch:会在使用之前,提前加载js文件,正常加载可以认为是并行加载,预加载会等其他文件加载完毕后再加载
*/
// 预加载实现方式: import(/* webpackPrefetch: true */'./test.js').then(() => {})