1.生成 package.json 文件
npm init -y
2.安装
webpack
webpack
ebpack-cli
cnpm install --save-dev webpack webpack-cli
//config/webpack.common.config.js 共有的配置
const path = require('path');//依次cd
module.exports = {
entry: { //entry(项目入口)
index: './src/index.js', //目录
framework: ['react','react-dom'], //模块
},
output: {//output(出口文件)
filename: 'js/[name].[chunkhash:8].bundle.js', //不确定打包名字
path: path.resolve(__dirname, '../dist'),//__dirname总是指向文件绝对路径
clean: true, // 每次打包清除输出目录.
}
module: {//module(模块的处理)
rules: [//在rules中配置:识别文件类型 并 使用相关loader进行转换
···
]
}
plugins: [ //plugin(loader不能做的处理都能交给plugin来做)
new HtmlWebpackPlugin({ //一种插件就是一种函数
···
},
})
]
optimization: { //优化
···
},
}
webpack-merge
webpack-merge
通过“通用”配置,配置生产/开发环境。
cnpm install --save-dev webpack-merge
webpack.config文件中通过const {merge} = require('webpack-merge');引入merge函数使用
//config/ebpack.prod.config.js 生产环境的配置
const {merge} = require('webpack-merge'); //引入merge(函数)
const common = require('./webpack.common.config.js');//引入共有的配置
//merge类似与字符串连接
module.exports = merge(common, {
···
});
HtmlWebpackPlugin 自动编译html并引入js文件
html-webpack-plugin
cnpm install --save-dev html-webpack-plugin
在webpack.config中先引入插件
const HtmlWebpackPlugin = require('html-webpack-plugin');
,然后再配置 plugins 属性使用
//config/ebpack.prod.config.js 生产环境的配置
const HtmlWebpackPlugin = require('html-webpack-plugin');
//merge类似与字符串连接
module.exports = merge(common, {
···
//一种插件就是一种函数
plugins: [
new HtmlWebpackPlugin({
filename: 'index.html', \\打包后输出的html文件名
template: 'public/index.html', \\以(输入的html)为模板
inject: 'body', \\在body最底部引入js(head就是head中引入)
minify: { \\[压缩html文件](https://github.com/jantimon/html-webpack-plugin#minification)
removeComments: true, \\去除注释
collapseWhitespace: true, \\去除空格
},
})
]
});
React
react
react-dom
react-router-dom
cnpm install --save react react-dom react-router-dom
babel 转译js/jsx
babel-loader
@babel/preset-react
@babel/preset-env
@babel/core
- babel-loader:使用Babel和webpack来转译JavaScript文件。
- @babel/preset-react:转译react的JSX
- @babel/preset-env:转译ES2015+的语法
- @babel/core:babel的核心模块
cnpm install --save-dev babel-loader @babel/preset-react @babel/preset-env @babel/core
根目录新增babel.config.json配置文件,在module.rules中通过use:'babel-loader'使用
//config/webpack.common.config.js 共有的配置
module.exports = {
···
module: {
rules: [
{
test: /\.(js|jsx)$/, //表示匹配规则,是一个正则表达式
use: 'babel-loader', //表示针对匹配文件将使用处理的loader
exclude: /node_modules/, //exclude 告诉我们不需要去转译"node_modules"这里面的文件
}
]
}
}
style-loader和css-loader
style-loader
css-loader
cnpm install --save-dev style-loader css-loader
webpack loader的执行顺序是从右到左,遇到后缀为.css的文件,遇到“@import”等语句就将相应样式文件引入,webpack先用css-loader加载器解析,计算完的css,使用style-loader生成最终css代码的style标签,放到head标签里。
把style-loader放在css-loader的前面
//config/webpack.common.config.js 共有的配置
module.exports = {
···
module: {
rules: [
···
{
test: /\.css$/,
use: [
'style-loader', //用MiniCssExtractPlugin.loader代替
'css-loader'
]
}
]
}
}
mini-css-extract-plugin 打包出CSS独立文件
mini-css-extract-plugin
在webpack.config中先引入插件
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
,然后再配置 plugins , 最后修改loader使用。
cnpm install --save-dev mini-css-extract-plugin
//config/webpack.common.config.js 共有的配置
const MiniCssExtractPlugin = require('mini-css-extract-plugin'); //引入
module.exports = {
···
plugins: [
//...
new MiniCssExtractPlugin({
filename: 'css/[name].[hash].css',
chunkFilename: 'css/[id].[hash].css',
}),
]
}
//config/webpack.common.config.js 共有的配置
module.exports = {
···
module: {
rules: [
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader'
]
}
]
}
}
CssMinimizerWebpackPlugin 压缩css
css-minimizer-webpack-plugin
cnpm install css-minimizer-webpack-plugin --save-dev
在webpack.config中先引入插件
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
,然后再配置 optimization 使用。
//config/webpack.prod.config.js 共有的配置
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
module.exports = {
···
optimization: {
···
minimizer: [
`...`, //使用 `...` 语法来扩展现有的 minimizer
new CssMinimizerPlugin(),
],
},
}
less-loader 转译less
less
less-loader
cnpm install --save-dev less less-loader
rules中设置loader使用。
//config/webpack.prod.config.js 共有的配置
module.exports = {
···
module: {
rules: [
···
{
test: /\.less$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'less-loader'
]
},
]
}
}
sass-loader 转译sass
sass-loader
sass
这里的sass就是dart sass
cnpm install sass-loader sass --save-dev
rules中设置loader使用。
//config/webpack.prod.config.js 共有的配置
module.exports = {
···
module: {
rules: [
···
{
test: /\.(sass|scss)$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'sass-loader'
]
},
]
}
}
postcss-loader 转译css
postcss-loader
postcss
cnpm install --save-dev postcss-loader postcss
postcss 一种对css编译的工具,类似babel对js的处理,常见的功能如:
1 . 使用下一代css语法
2 . 自动补全浏览器前缀
3 . 自动把px代为转换成rem
4 . css 代码压缩等等
postcss 只是一个工具,本身不会对css一顿操作,它通过插件实现功能,autoprefixer 就是其一。
1.安装postcss某个插件,以Autoprefixer举例
cnpm install autoprefixer --save-dev
。
2.在根目录新建postcss.config.js
3.rules中设置loader
//postcss.config.js #postcss配置文件
module.exports = {
plugins: [
require('autoprefixer')({ browsers: ['last 5 version', '>1%', 'ie >=8'] })
]
};
//config/webpack.prod.config.js 共有的配置
module.exports = merge(common, {
//...
module: {
rules: [
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'postcss-loader'
]
},
{
test: /\.less$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'postcss-loader',
'less-loader'
]
},
{
test: /\.(scss|sass)$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'postcss-loader',
'sass-loader'
]
},
]
},
//...
});
内置的 Asset Modules 管理资源(加载图像、font等)
在rules中设置
asset/resource
将资源分割为单独的文件,并导出url
asset/inline
将资源导出为dataURL(url(data:))的形式
asset/source
将资源导出为源码(source code)
asset
自动选择导出为单独文件或者 dataURL形式(默认为8KB)
//postcss.config.js #postcss配置文件
module.exports = {
···
module: {
rules: [
···
{ // 加载 images 图像
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: 'asset/resource',
},
{ //加载fonts字体
test: /\.(woff|woff2|eot|ttf|otf)$/i,
type: 'asset/resource',
},
],
},
};
eslint-plugin-react-hooks 强制执行两条hook规则
eslint
eslint-plugin-react-hooks
cnpm install eslint eslint-plugin-react-hooks --save-dev
在package.json中设置
//package.json
{
···
// 你的 ESLint 配置
"eslintConfig": {
"plugins": [
"react-hooks"
],
"rules": {
"react-hooks/rules-of-hooks": "error", // 检查 Hook 的规则
"react-hooks/exhaustive-deps": "warn" // 检查 effect 的依赖
}
},
···
}
React Router Dom
react-router-dom
cnpm install react-router-dom --save
配置开发服务器解决BrowserRouter刷新"cannot GET /URL" 问题
//config/webpack.common.config.js 默认环境的配置
output: {
publicPath: '/',//向index.html织入<script>时src的前缀。"app.js"-->"/app.js",转为绝对位置
···
},
//config/webpack.dev.config.js 开发环境的配置
···
module.exports = merge(common, {
···
devServer: {
historyApiFallback: true,//默认指向index,解决BrowserRouter刷新"cannot GET /URL" 问题
···
},
···
},
SplitChunksPlugin 代码分割及去重
webpack v4+ 自带
配置optimization.splitChunks使用
//config/ebpack.prod.config.js 生产环境的配置
module.exports = merge(common, {
···
optimization: {
splitChunks: {
chunks: 'all', //选择哪些 chunk 进行优化。
minSize: 20000, //生成 chunk 的最小体积(以 bytes 为单位)。
minChunks: 1, //拆分前必须共享模块的最小 chunks 数。
//maxSize: 0, // 尝试将大于 maxSize 个字节的 chunk 分割成较小的部分。
maxAsyncRequests: 30, //按需加载时的最大并行请求数。
maxInitialRequests: 30, //入口点的最大并行请求数。
enforceSizeThreshold: 50000, //强制执行拆分的体积阈值和其他限制(minRemainingSize,maxAsyncRequests,maxInitialRequests)将被忽略。
cacheGroups: { //定义了需要被抽离的模块
framework: {
test: "framework", //匹配入口名
name: "framework",
enforce: true
},
vendors: {
priority: -10,
test: /node_modules/, //匹配目录下引入的模块
filename: 'js/vendors/[name].[chunkhash:8].bundle.js',// 输出路径
name: "vendor",
enforce: true,
},
},
},
},
});
terser-webpack-plugin 压缩js
webpack v5 自带
//config/ebpack.prod.config.js 生产环境的配置
const TerserPlugin = require("terser-webpack-plugin");
module.exports = {
optimization: {
minimize: true,
minimizer: [new TerserPlugin()],
},
};
webpack-dev-server 开发服务器
webpack-dev-server
cnpm install webpack-dev-server --save-dev
//config/webpack.dev.config.js 开发环境的配置
···
const webpack = require('webpack');
module.exports = merge(common, {
···
devServer: {
historyApiFallback: true,//BrowserRouter解决刷新"cannot GET /URL" 问题
contentBase: path.resolve(__dirname, '../dist'),
open: true,
port: 9000,
compress: true,
hot: true //开启热更新 需要热更新插件
},
plugins: [
···
new webpack.HotModuleReplacementPlugin(), // webpack热更新的插件
]
});
//package.json 开发环境的配置
"scripts": {
···
"start": "webpack serve --inline --config ./config/webpack.dev.config.js",
···
},
3.目录
frontend
|- config #使用webpack-merge配置不同环境
|- webpack.common.config.js
|- webpack.prod.config.js
|- webpack.dev.config.js
|- node_modules # 依赖包
|- ···
|- public #公共文件存放地址
|- index.html
|- src
|- images
|-111.jpg
|- index.js
|- app.js
|- app.less
|- babel.config.json #babel配置文件
|- package.json
|- postcss.config.js
4.配置
package.json
//package.json
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
//命令:webpack --config选项来指定配置文件
"start": "webpack serve --inline --config ./config/webpack.dev.config.js",
"build": "webpack --config ./config/webpack.prod.config.js"
},
// 你的 ESLint 配置
"eslintConfig": {
"plugins": [
"react-hooks"
],
"rules": {
"react-hooks/rules-of-hooks": "error", // 检查 Hook 的规则
"react-hooks/exhaustive-deps": "warn" // 检查 effect 的依赖
}
},
postcss.config.js
//postcss.config.js
module.exports = {
plugins: [
require('autoprefixer')({ browsers: ['last 5 version', '>1%', 'ie >=8'] })
]
};
babel 配置
根目录新建babel.config.json
配置相关的"presets":
//babel.config.json
{
"presets": [
[
"@babel/env",
{
"targets": {
"edge": "17",
"firefox": "60",
"chrome": "67",
"safari": "11.1"
},
"useBuiltIns": "usage",
"corejs": "3.6.4"
}
],
"@babel/preset-react"
]
}
webpack配置 webpack-merge使用 HtmlWebpackPlugin使用 代码分离(及去重)
- 共有的配置
//config/webpack.common.config.js 共有的配置
const path = require('path');//依次cd
module.exports = {
//entry(项目入口)
entry: {
index: './src/index.js',
framework: ['react','react-dom'],
},
//output(出口文件)
output: {
publicPath: '/',//向index.html织入<script>时src的前缀。"app.js"-->"/app.js",转为绝对位置
filename: 'js/bundle.js',
path: path.resolve(__dirname, '../dist'),//__dirname总是指向文件绝对路径
clean: true, // 每次打包清除输出目录.
}
//module(模块的处理)
//在rules中配置:识别文件类型 并 使用相关loader进行转换
module: {
rules: [
{
test: /\.(js|jsx)$/, //表示匹配规则,是一个正则表达式
use: 'babel-loader', //表示针对匹配文件将使用处理的loader
exclude: /node_modules/, //exclude 告诉我们不需要去转译"node_modules"这里面的文件
},
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader' ,
'postcss-loader',
]
},
{
test: /\.less$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'postcss-loader',
'less-loader'
]
},
{
test: /\.(sass|scss)$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'postcss-loader',
'sass-loader'
]
},
{ // 加载 images 图像
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: 'asset/resource',
},
{ //加载fonts字体
test: /\.(woff|woff2|eot|ttf|otf)$/i,
type: 'asset/resource',
},
]
}
//plugin(loader不能做的处理都能交给plugin来做)
plugins: [
//...
new MiniCssExtractPlugin({
filename: 'css/[name].[hash].css',
chunkFilename: 'css/[id].[hash].css',
}),
]
}
- 生产环境的配置
//config/ebpack.prod.config.js 生产环境的配置
const {merge} = require('webpack-merge'); //引入merge(函数)
const common = require('./webpack.common.config.js');//引入共有的配置
const HtmlWebpackPlugin = require('html-webpack-plugin');
//merge类似与字符串连接
module.exports = merge(common, {
mode: 'production',
devtool: 'source-map',
output: { //给打包出的js文件换个不确定名字
filename: 'js/[name].[chunkhash:8].bundle.js',
},
//一种插件就是一种函数
plugins: [
new HtmlWebpackPlugin({ \\自动编译html并引入js文件
filename: 'index.html', \\打包后输出的html文件名
template: 'public/index.html', \\以(输入的html)为模板
inject: 'body', \\在body最底部引入js(head就是head中引入)
minify: { \\[压缩html文件](https://github.com/jantimon/html-webpack-plugin#minification)
removeComments: true, \\去除注释
collapseWhitespace: true, \\去除空格
},
})
],
optimization: {
splitChunks: {
chunks: 'all', //选择哪些 chunk 进行优化。
minSize: 20000, //生成 chunk 的最小体积(以 bytes 为单位)。
minChunks: 1, //拆分前必须共享模块的最小 chunks 数。
//maxSize: 0, // 尝试将大于 maxSize 个字节的 chunk 分割成较小的部分。
maxAsyncRequests: 30, //按需加载时的最大并行请求数。
maxInitialRequests: 30, //入口点的最大并行请求数。
enforceSizeThreshold: 50000, //强制执行拆分的体积阈值和其他限制(minRemainingSize,maxAsyncRequests,maxInitialRequests)将被忽略。
cacheGroups: { //定义了需要被抽离的模块
framework: {
test: "framework",
name: "framework",
enforce: true
},
vendors: {
priority: -10,
test: /node_modules/, //匹配目录下引入的模块
filename: 'js/vendors/[name].[chunkhash:8].bundle.js',// 输出路径
name: "vendor",
enforce: true,
},
},
},
minimize: true, //压缩
minimizer: [new TerserPlugin(),], //压缩
},
});
- 开发环境的配置
//config/webpack.prod.config.js 开发环境的配置
const path = require('path');
const {merge} = require('webpack-merge');
const common = require('./webpack.common.config.js');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = merge(common, {
mode: 'development',
devtool: 'eval-source-map',
output: {
filename: 'js/[name].[hash:8].bundle.js',
},
devServer: {
contentBase: path.resolve(__dirname, '../dist'),
open: true,
port: 9000,
compress: true,
hot: true, //开启热更新 需要热更新插件
},
plugins: [
new HtmlWebpackPlugin({
template: 'public/index.html',
inject: 'body',
hash: false
}),
new webpack.HotModuleReplacementPlugin(),// webpack热更新的插件
]
});