React项目中webpack的配置过程
初始化一个web项目
使用npm init -y 初始化一个项目
在项目目录下创建src, dist文件夹,创建webpack.config.js配置文件
然后在src文件夹下创建index.js, index.html文件
然后安装依赖包 npm i jquery -S 安装jQuery包 npm i webpack webpack-cli webpack-dev-server html-webpack-plugin -D 安装开发调试包 安装loader调试工具 yarn add style-loader css-loader sass-loader node-sass url-loader file-loader --dev 安装babel预编译工具, babel-loader@7需要添加版本号,否则可能导致babel-loader与babel-core版本不兼容问题 yarn add babel-loader@7 babel-core babel-plugin-transform-runtime babel-preset-env babel-preset-stage-0 babel-preset-react --dev 安装项目工具和UI库 yarn add react react-dom react-router-dom@4.2.2 antd@5.10.1
编写index.js脚本文件
import $ from 'jquery' $(function () { $('li:odd').css('backgroundColor','pink') $('li:even').css('backgroundColor','lightblue') })
在index.html中导入index.js脚本文件
<head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script src="./index.js"></script> </head>
编写webpack.config.js配置文件
const path = require('path') const htmlWebpackPlugin = require('html-webpack-plugin') module.exports = { mode: 'development', //项目的入口与出口设置 entry: path.join(__dirname, './src/index.js'), output: { path: path.join(__dirname, './dist'), filename: 'bundle.js' }, plugins: [ //插件 //在内存中生成一个页面,默认在项目的根目录下的内存中 new htmlWebpackPlugin({ //页面模板 template: path.join(__dirname, './src/index.html'), filename: 'index.html' }) ] }
在package.json项目配置中添加短命令
"scripts": { "test": "echo \"Error: no test specified\" && exit 1", // --cacheBase: 指定托管目录, 如果没指定默认在项目内存的根目录下 "dev": "webpack-dev-server --open --port 3000 --hot" },
执行npm run dev 进行打包调试
添加调试工具
添加loader加载器和babel预编译工具
添加loader加载器,让webpack处理js模块外的其他模块。
webpack默认只能打包处理以.js结尾的模块。其他非.js后缀名结尾的模块,webpack默认是不处理的。
需要调用loader加载器才可以正常打包,loader加载器的作用:协作webpack打包处理约定的文件模块。比如:css-loader: 可以打包处理.css相关的文件。
使用scss设置css样式,需要使用css-loader解析器进行解析 npm i style-loader css-loader sass-loader node-sass url-loader file-loader -D js中es6高级语法解析 npm i babel-core babel-loader babel-plugin-transform-runtime babel-preset-env babel-preset-stage-0 -D 在webpack.config.js中添加loader加载器配置 module: { rules: [ { test: /\.css$/, use:['style-loader', 'css-loader'] }, { test: /\.scss$/, use:['style-loader', 'css-loader', 'sass-loader'] }, { test: /\.(png|gif|bmp|jpg)$/, use: 'url-loader?limit=500000' }, { test: /\.js$/, use:'babel-loader', exclude: /node_modules/ }, ] }
开发完成,打包发布
新建发布配置文件webpack.pub.config.js
修改它的产物名称配置文件
module: { rules: [ { test: /\.css$/, use:['style-loader', 'css-loader'] }, { test: /\.scss$/, use:['style-loader', 'css-loader', 'sass-loader'] }, { test: /\.(png|gif|bmp|jpg)$/, use: 'url-loader?limit=5000&name=[hash:8]-[name].[ext]' }, { test: /\.js$/, use:'babel-loader', exclude: /node_modules/ }, ] }
在package.json配置文件中,添加短命令pub,并在webpack命令中添加使用的配置文件名参数
"scripts": { "test": "echo \"Error: no test specified\" && exit 1", "--cacheBase": "指定托管目录, 如果没指定默认在项目内存的根目录下", "dev": "webpack-dev-server --open --port 3000 --hot", "pub": "webpack --config webpack.pub.config.js" },
调用指令npm run pub, 打包出资源bundle.js, 图片, index.html。
zhoufeideMacBook-Pro-2:webpack zhoufei$ npm run pub > webpack@1.0.0 pub > webpack --config webpack.pub.config.js assets by path *.jpg 61.5 KiB asset 56e2b290-phone1.jpg 61.5 KiB [emitted] [immutable] [from: src/images/phone1.jpg] (auxiliary name: main) asset 7a417220207de157cf21.jpg 63 bytes [emitted] [immutable] [from: src/images/phone1.jpg] (auxiliary name: main) asset bundle.js 344 KiB [emitted] (name: main) asset index.html 660 bytes [emitted]
webpack编译器优化
1.产物图片优化
把项目中的所有图片在产物中放到一个images文件夹下面
通过修改webpack.pub.config.js中的module.rules项
{ test: /\.(png|gif|bmp|jpg)$/, use: 'url-loader?limit=5000&name=images/[hash:8]-[name].[ext]' },
2.产物目录dist重建优化
每次生成产物时,都对dist目录进行先清理,再生成
npm i clean-webpack-plugin -D webpack.pub.config.js中进行配置清理插件 const { CleanWebpackPlugin } = require('clean-webpack-plugin'); plugins: [ //插件 /* 每次构建产物都要重新创建dist目录保存产物 */ new CleanWebpackPlugin({cleanAfterEveryBuildPatterns:['dist']}) ],
3.抽离第三方包
发布思路:bundle.js中只存放自己的代码,第三方包的代码都抽离到另外的JS包中
webpack@4以后的版本,弃用了许多@3的插件,其中包括:
分离打包js文件的插件 webpack.optimize.CommonChunkPlugin(); 压缩js文件的插件 webpack.optimize.UglifyJsPlugin(); 定义产品上线环境webpack.optimize.DedupePlugun(); 分离css文件插件extract-text-webpack-plugin(); css文件压缩插件 CssMinimizerPlugin();
webpack3的抽离方法
在webpack.pub.config.js中修改entry的设置为如下: //app和vendors的key名称都是自己自定义的,随便取的 entry: { app: path.join(__dirname, './src/index.js'), vendors: ['jquery'] //把要抽离的第三方包放到这个数组中 }, 在pulgins的数组中添加抽离设置 new webpack.optimize.CommonsChunkPlugin({ name: 'vendors', //指定抽离的入口 filename: 'vendors.js' //抽离的所有第三方包的结果包名称。 }) 然后将js文件放到一个统一的目录下: output: { path: path.join(__dirname, './dist'), filename: 'js/bundle.js' },
4.压缩js代码
在webpack.pub.config.js中的 plugins项目下,添加下面的js优化代码
js代码压缩优化 new webpack.optimize.UglifyJsPlugin({ compress: { //配置压缩项 warnings: false //移除警告 } }), new webpack.optimize.DedupePlugin({ 'process.env.NODE_ENV': '"production"' })
5.压缩html代码
在htmlWebpackPlugin模板中添加html优化配置 new htmlWebpackPlugin({ //页面模板 template: path.join(__dirname, './src/index.html'), filename: 'index.html', minify: { collapseWhitespace: true, //合并多余的空格 removeComments: true, // 移除注释 removeAttributeQuotes: true //移除属性上的双引号 } }),
6.从bundle.js中抽离css单独存放
yarn add extract-text-webpack-plugin --dev 修改webpack.pub.config.js文件 const ExtractTextPlugin = require('extract-text-webpack-plugin') 添加插件 plugins: [ //插件 //配置提取出来的css名称 new ExtractTextPlugin({ filename: 'style/[name].min.css' }) ], 修改css-loader的rules module: { rules: [ { test: /\.css$/, use: ExtractTextPlugin.extract({ fallback: 'style-loader', use: 'css-loader', publicPath: '../' //指定抽离的时候,自动为我们使用的路径加上 ../前缀 }) }, { test: /\.scss$/, use: ExtractTextPlugin.extract({ fallback: 'style-loader', use: ['css-loader', 'sass-loader'], publicPath: '../' //指定抽离的时候,自动为我们使用的路径加上 ../前缀 }) }, ] }
7.压缩css
yarn add optimize-css-assets-webpack-plugin --dev 修改webpack.pub.config.js文件 // 压缩css插件 const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin') plugins: [ //插件 /* 压缩css */ new OptimizeCssAssetsPlugin() ],
webpack项目模板
dev的webpack开发模板
const path = require('path') const htmlWebpackPlugin = require('html-webpack-plugin') const { name } = require('file-loader') module.exports = { mode: 'development', //项目的入口与出口设置 entry: path.join(__dirname, './src/index.js'), output: { path: path.join(__dirname, './dist'), filename: 'bundle.js' }, plugins: [ //插件 //在内存中生成一个页面,默认在项目的根目录下的内存中 /* html-webpack-plugin的作用有2个: 1.自动将./src/index.html页面复制一份到项目根目录,放到了内存中。 2.在内存中自动生成的index.html页面里,自动注入webpack打包的存在于内存中的bundle.js文件 */ new htmlWebpackPlugin({ //页面模板 template: path.join(__dirname, './src/index.html'), filename: 'index.html' }) ], /* webpack默认只能打包处理以.js结尾的模块。其他非.js后缀名结尾的模块,webpack默认是不处理的。 需要调用loader加载器才可以正常打包,loader加载器的作用:协作webpack打包处理约定的文件模块。比如:css-loader: 可以打包处理.css相关的文件。 */ module: { rules: [ { test: /\.css$/, use:['style-loader', 'css-loader'] }, //声明css模块化,使用CSS模块化解决多个css的作用域都是全局作用域,导致结果互相覆盖的情况 //一般第三方库的样式文件是以css结尾的,所以不能直接对css开启模块化,会影响其他第三方库的展示,这里只对scss进行开启模块化 // { test: /\.css$/, use:['style-loader', { // loader: 'css-loader', // options: { // importLoaders: 1, // modules: true, // //自定义css模块化后的class名称 // // localIdentName: [name]-[local]-[hash:5] // } // }] }, { test: /\.scss$/, use:['style-loader', { loader: 'css-loader', options: { importLoaders: 1, modules: true, //自定义css模块化后的class名称 // localIdentName: [name]-[local]-[hash:5] } }, 'sass-loader'] }, { test: /\.(png|gif|bmp|jpg)$/, use: 'url-loader?limit=500000' }, { test: /\.jsx?$/, use:'babel-loader', exclude: /node_modules/ }, ] } }
pub的webpack发布模板
const path = require('path') const htmlWebpackPlugin = require('html-webpack-plugin') //导入每次删除文件夹的插件 const { CleanWebpackPlugin } = require('clean-webpack-plugin'); const webpack = require('webpack') // 抽取Css插件 const ExtractTextPlugin = require('extract-text-webpack-plugin') // 压缩css插件 const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin') module.exports = { mode: 'production', //项目的入口与出口设置 entry: path.join(__dirname, './src/index.js'), //app和vendors的key名称都是自己自定义的,随便取的 // entry: { // app: path.join(__dirname, './src/index.js'), // vendors: ['jquery'] //把要抽离的第三方包放到这个数组中 // }, output: { path: path.join(__dirname, './dist'), filename: 'js/bundle.js' }, plugins: [ //插件 //在内存中生成一个页面,默认在项目的根目录下的内存中 /* html-webpack-plugin的作用有2个: 1.自动将./src/index.html页面复制一份到项目根目录,放到了内存中。 2.在内存中自动生成的index.html页面里,自动注入webpack打包的存在于内存中的bundle.js文件 */ new htmlWebpackPlugin({ //页面模板 template: path.join(__dirname, './src/index.html'), filename: 'index.html', minify: { collapseWhitespace: true, //合并多余的空格 removeComments: true, // 移除注释 removeAttributeQuotes: true //移除属性上的双引号 } }), /* 每次构建产物都要重新创建dist目录保存产物 */ new CleanWebpackPlugin({cleanAfterEveryBuildPatterns:['dist']}), new OptimizeCssAssetsPlugin() /* 编译优化:抽离第三方包名称 webpack3的在plugins数组中添加new webpack.optimize.CommonsChunkPlugin配置方式已经废弃,要在下面的方法进行实现 webpack3实现方法 new webpack.optimize.CommonsChunkPlugin({ name: 'vendors', //指定抽离的入口 filename: 'vendors.js' //抽离的所有第三方包的结果包名称。 }) webpack5设置无效,先注释 */ /* 编译优化:js代码压缩优化 new webpack.optimize.UglifyJsPlugin({ compress: { //配置压缩项 warnings: false //移除警告 } }), new webpack.optimize.DedupePlugin({ 'process.env.NODE_ENV': '"production"' }) */ /* 编译优化:抽离css //配置提取出来的css名称 new ExtractTextPlugin({ filename: 'style/[name].min.css' }) */ ], // webpack V5替代webpack V3的解决方案 // optimization: { // splitChunks: { // cacheGroups: { // commons: { // test: /[\\/]node_modules[\\/]/, // name: 'vendors', // chunks: 'all', // }, // } // } // }, /* webpack默认只能打包处理以.js结尾的模块。其他非.js后缀名结尾的模块,webpack默认是不处理的。 需要调用loader加载器才可以正常打包,loader加载器的作用:协作webpack打包处理约定的文件模块。比如:css-loader: 可以打包处理.css相关的文件。 产物图片优化: 把项目中的所有图片在产物中放到一个images文件夹下面 { test: /\.(png|gif|bmp|jpg)$/, use: 'url-loader?limit=5000&name=images/[hash:8]-[name].[ext]' }, */ module: { rules: [ { test: /\.css$/, use:['style-loader', 'css-loader'] }, //声明css模块化,使用CSS模块化解决多个css的作用域都是全局作用域,导致结果互相覆盖的情况 //一般第三方库的样式文件是以css结尾的,所以不能直接对css开启模块化,会影响其他第三方库的展示,这里只对scss进行开启模块化 // { test: /\.css$/, use:['style-loader', { // loader: 'css-loader', // options: { // importLoaders: 1, // modules: true, // //自定义css模块化后的class名称 // // localIdentName: [name]-[local]-[hash:5] // } // }] }, { test: /\.scss$/, use:['style-loader', { loader: 'css-loader', options: { importLoaders: 1, modules: true, //自定义css模块化后的class名称 // localIdentName: [name]-[local]-[hash:5] } }, 'sass-loader'] }, { test: /\.(png|gif|bmp|jpg)$/, use: 'url-loader?limit=500000' }, { test: /\.jsx?$/, use:'babel-loader', exclude: /node_modules/ }, ] } }
对应package.json依赖关系和scripts短命令
{ "name": "webpack", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "--cacheBase": "指定托管目录, 如果没指定默认在项目内存的根目录下", "dev": "webpack-dev-server --open --port 3000 --hot", "pub": "webpack --config webpack.pub.config.js" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "babel-core": "^6.26.3", "babel-loader": "7", "babel-plugin-transform-runtime": "^6.23.0", "babel-preset-env": "^1.7.0", "babel-preset-react": "^6.24.1", "babel-preset-stage-0": "^6.24.1", "clean-webpack-plugin": "^4.0.0", "css-loader": "^6.8.1", "extract-text-webpack-plugin": "^3.0.2", "file-loader": "^6.2.0", "html-webpack-plugin": "^5.5.3", "node-sass": "^9.0.0", "optimize-css-assets-webpack-plugin": "^6.0.1", "sass-loader": "^13.3.2", "style-loader": "^3.3.3", "url-loader": "^4.1.1", "webpack": "^5.89.0", "webpack-cli": "^5.1.4", "webpack-dev-server": "^4.15.1" }, "dependencies": { "antd": "^5.10.1", "jquery": "^3.7.1", "prop-types": "^15.8.1", "react": "^18.2.0", "react-dom": "^18.2.0", "react-router-dom": "4.2.2" } }
.babelrc模板
{ "presets": ["env", "stage-0", "react"], "plugins": ["transform-runtime"] }