1、config/webpack.base.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { VueLoaderPlugin } = require('vue-loader');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const NODE_ENV = process.env.NODE_ENV;
console.log(NODE_ENV);
module.exports = {
entry: './src/index.js',
module: {
rules: [
{
test: /\.vue$/i,
loader: 'vue-loader',
options: {
css: [
NODE_ENV === 'production' ? MiniCssExtractPlugin.loader : 'vue-style-loader',
'css-loader',
'postcss-loader',
'sass-loader'
]
},
include: /src/
},
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: [
'thread-loader',
'babel-loader?cacheDirectory'
],
include: /src/
},
{
test: /\.css$/i,
use: [NODE_ENV === 'production' ? MiniCssExtractPlugin.loader : 'style-loader', 'css-loader', 'postcss-loader'],
include: /src/
},
{
test: /\.less$/i,
use: [NODE_ENV === 'production' ? MiniCssExtractPlugin.loader : 'style-loader', 'css-loader', 'postcss-loader', 'less-loader'],
include: /src/
},
{
test: /\.s[ac]ss$/i,
use: [NODE_ENV === 'production' ? MiniCssExtractPlugin.loader : 'style-loader', 'css-loader', 'postcss-loader', 'sass-loader'],
include: /src/
},
{
test: /\.(png|jpe?g|gif)$/i,
use: [
{
loader: 'url-loader',
options: {
limit: 8192,
name: 'assets/images/[name]_[hash:6].[ext]'
},
},
],
include: /src/
},
{
test: /\.html$/i,
loader: 'html-loader',
include: /src/
},
{
test: /\.(png|jpe?g|gif)$/i,
use: [
{
loader: 'file-loader',
options: {
name: 'assets/media/[name]_[hash:6].[ext]'
}
},
],
include: /src/
}
],
},
resolve: {
extensions: ['.vue', '.js', '.json', '.css', 'less', 'scss'],
alias: {
'vue$': 'vue/dist/vue.esm.js'
}
},
plugins: [
new VueLoaderPlugin(),
new HtmlWebpackPlugin({
template: './public/index.html'
})
]
}
2、config/webpack.dev.config.js
const path = require('path');
const { merge } = require('webpack-merge');
const commonConfig = require('./webpack.base.config');
function resolve(p) {
return path.resolve(__dirname, p);
}
module.exports = merge(commonConfig, {
mode: 'development',
output: {
path: resolve('../dist'),
filename: 'js/build.js'
},
devServer: {
contentBase: resolve('../dist'),
compress: true,
hot: true,
open: false,
port: 9000,
proxy: {
'/api': {
target: 'http://localhost:3000',
pathRewrite: { '^/api': '' }
},
},
}
});
3、config/webpack.prod.config.js
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const { merge } = require('webpack-merge');
const commonConfig = require('./webpack.base.config');
function resolve(p) {
return path.resolve(__dirname, p);
}
module.exports = merge(commonConfig, {
mode: 'production',
output: {
path: resolve('../dist'),
filename: 'js/[name].[chunkhash:6].js'
},
optimization: {
minimize: true,
minimizer: [
new CssMinimizerPlugin({
parallel: true,
}),
new TerserPlugin({
cache: true,
parallel: true
})
],
runtimeChunk: {
name: (entrypoint) => `runtime~${entrypoint.name}`,
},
splitChunks: {
chunks: "all"
}
},
plugins: [
new CleanWebpackPlugin(),
new MiniCssExtractPlugin({
filename: 'css/[name].[contenthash:6].css',
chunkFilename: 'css/[id].[contenthash:6].css'
})
]
})
4、.babelrc
{
"presets": [
[
"@babel/preset-env",
{
"useBuiltIns": "usage",
"corejs": {
"version": 3
},
"targets": {
"chrome": "40",
"firefox": "40",
"ie": "9",
"safari": "10",
"edge": "15"
}
}
]
],
"plugins": [
"@babel/plugin-transform-runtime",
"@babel/plugin-syntax-dynamic-import"
]
}
5、postcss.config.js
module.exports = {
plugins: [
[
"postcss-preset-env"
]
]
}
6、package.json
{
"name": "webpack-study",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"dev": "cross-env NODE_ENV=development webpack-dev-server --config ./config/webpack.dev.config.js",
"build": "cross-env NODE_ENV=production webpack --config ./config/webpack.prod.config.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@babel/core": "^7.13.10",
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
"@babel/plugin-transform-runtime": "^7.13.10",
"@babel/preset-env": "^7.13.12",
"babel-loader": "^8.2.2",
"clean-webpack-plugin": "^3.0.0",
"core-js": "^3.9.1",
"cross-env": "^7.0.3",
"css-loader": "^5.1.3",
"css-minimizer-webpack-plugin": "^1.3.0",
"express": "^4.17.1",
"file-loader": "^6.2.0",
"html-loader": "^1.3.2",
"html-webpack-plugin": "^4.5.2",
"less": "^4.1.1",
"less-loader": "^7.3.0",
"mini-css-extract-plugin": "^1.3.9",
"postcss-loader": "^4.2.0",
"postcss-preset-env": "^6.7.0",
"sass": "^1.32.8",
"sass-loader": "^10.1.1",
"style-loader": "^2.0.0",
"terser-webpack-plugin": "^4.2.3",
"thread-loader": "^3.0.1",
"url-loader": "^4.1.1",
"vue-loader": "^15.9.6",
"vue-style-loader": "^4.1.3",
"vue-template-compiler": "^2.6.12",
"webpack": "^4.46.0",
"webpack-cli": "^3.3.12",
"webpack-dev-server": "^3.11.2",
"webpack-merge": "^5.7.3"
},
"dependencies": {
"@babel/runtime": "^7.13.10",
"vue": "^2.6.12",
"vue-router": "^3.5.1"
},
"browserslist": {
"development": [
"last 4 chrome version",
"last 4 firefox version",
"last 4 safari version"
],
"production": [
">0.2%",
"not dead",
"not op_mini all"
]
}
}
7、性能优化部分
# webpack4学习笔记
## 一、项目基础文件
-- src、config、public文件夹,index.html、index.js
## 二、配置webpack.config.js
-- 1.装包
npm i webpack webpack-cli -D
-- 2.配置入口和出口
-- 3.应用HTML模板
npm install html-webpack-plugin -D
-- 4.修改npm启动命令
-- 5、处理样式资源
## 性能优化
### 1、CSS和JS代码压缩
### 2、CSS抽离成单独文件,按需加载
### 3、HMR,只重新加载已改变的文件
### 4、oneOf,每个文件loader只处理一次
### 5、babel缓存,提高打包速度。
### 6、JS文件设置chunkhash,CSS文件contenthash,设置缓存,hash值不变,直接取缓存文件渲染
### 7、tree shaking,去掉没有用到的代码
前提:1、必须使用ES6模块化。2、开启production环境
只要是模块化,打包后会自动去掉无用代码
### 8、代码分割---splitChunks
抽离公共代码、第三方库
自动分析多入口chunk中有没有公共的文件。如果有会打包成单独的chunk,避免重复打包多次
ES10的import('url')动态导入语法可将文件单独打包成一个chunk,类似vue的路由懒加载语法
splitChunks: {
chunks: "all"
}
这样会有个问题,main.js中记录其他文件的hash值,如果其他文件变了,main.js也会重新打包
runtimeChunk为每个只含有 runtime 的入口添加一个额外 chunk
runtimeChunk: {
name: (entrypoint) => `runtime~${entrypoint.name}`,
}
-- hash:每次webpack构建时会生成一个唯一的hash值。一个文件改变,所有的hash值都会变
chunkhash:根据chunk生成的hash值。如果JS和CSS都用chunkhash,因为JS和CSS属于同一个chunk,因此hash值一样,某一个文件改变时,同一个chunk的JS和CSS都会重新打包
contenthash:根据文件的内容生成hash值。不同文件hash值一定不一样
优化:JS文件用chunkhash,CSS文件用contenthash
-- 多进程打包 thread-loader