1.创建新项目目录,并进入文件夹,初始化package.json文件
mkdir webpack5-pro
cd webpack5-pro
npm init -y
2.安装webpack和webpack-cli
npm i webpack webpack-cli -D
查看
package.json文件,可以看到webpack、webpack-cli的包已经安装成功。
{
"name": "Code",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
// 开发环境依赖
"webpack": "^5.67.0",
"webpack-cli": "^4.9.2"
}
}
3.创建项目的源码目录src
工程化项目的源代码目录
src创建完成之后,新建项目的入口文件index.js,写入一下测试代码:
function helloWebpack (name){
console.log("webpack,你好啊!我是" + name )
}
helloWebpack("hunhunzhang")
4.在项目根目录下新建webpack打包后的文件输出的目录dist和webpack.config.js配置文件
// webpack.config.js文件的基本配置如下
const path = require("path")
module.exports = {
// 打包模式
// mode: 'development',
// 入口文件
entry: path.resolve(__dirname,'./src/index.js'),
// 出口目录
output: {
filename: 'bundle.js',
path: path.resolve(__dirname,'./dist')
}
}
5.修改package.json文件的scripts脚本配置,启用webpack
{
"name": "Code",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
// webpack打包脚本配置
"build": "webpack"
}
}
6.初次打包,测试打包情况,运行命令后,当你看到dist的目录下有bundle.js文件,说明成功
// 运行测试打包的脚本命令
npm run build
// 打包后的bundle.js文件内容
/*
* ATTENTION: The "eval" devtool has been used (maybe by default in mode: "development").
* This devtool is neither made for production nor for readable output files.
* It uses "eval()" calls to create a separate source file in the browser devtools.
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
* or disable the default devtool with "devtool: false".
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
*/
/******/ (() => { // webpackBootstrap
/******/ var __webpack_modules__ = ({
/***/ "./src/index.js":
/*!**********************!*\
!*** ./src/index.js ***!
\**********************/
/***/ (() => {
eval("function helloweb(name){\r\n\tconsole.log('hwlo' + name)\r\n}\r\nhelloweb('hhz')\n\n//# sourceURL=webpack://Code/./src/index.js?");
/***/ })
/******/ });
/************************************************************************/
/******/
/******/ // startup
/******/ // Load entry module and return exports
/******/ // This entry module can't be inlined because the eval devtool is used.
/******/ var __webpack_exports__ = {};
/******/ __webpack_modules__["./src/index.js"]();
/******/
/******/ })()
;
7.区分打包的的环境时生产(prod)还是开发(dev),分类处理
当项目较大时候,需要根据不同的环境进行不同的配置来完成想要的操作,所以,需要拆分webpack配置文件:
1)创建一个config文件夹,用来存放不同配置的文件:
webpack.common.js用来配置webpack公共的配置webpack.dev.js开发环境的配置webpack.prod.js生产环境的配置
2)在不同的配置文件中,使用webpack-merge中的merge来合并公共的webpack文件(webpack4是根据smart来进行合并配置的)
npm i webpack-merge -D
3)不同配置文件的源码:
webpack.common.js
const path = require("path")
const srcPath = path.join(__dirname,"..","src")
module.exports = {
entry: path.join(srcPath,"index.js")
}
webpack.dev.js
const path = require("path")
const conmonConfig = require("./webpack.common")
const { merge } = require("webpack-merge")
const devConfig = {
mode: 'development',
output: {
filename: "bundle.js",
path: path.join(__dirname,"..","dist")
}
}
module.exports = merge(commonConfig,devConfig)
webpack.prod.js
const path = require('path')
const commonConfig = require('./webpack.common.js')
const {merge} = require('webpack-merge')
const prodConfig = {
mode: 'production', // 生产环境
output: {
filename: 'bundle.[chunkhash].js', // 输出文件名,一般要加上hash
path: path.join(__dirname, '..', 'dist') // 输出目录
}
}
module.exports = merge(commonConfig, prodConfig)
8.package.json中配置不同webpack环境的命令:
为了让我们在开发阶段,不需要修改一次文件就手动的去进行
webpack进行编译,所以安装webpack-dev-server插件来进行开发:
npm i webpack-dev-server -D
注意:在
webpack4中开发环境使用的命令是webpack-dev-server --config config/webpack.dev.js,在webpack5中,改成了webpack server。脚本命令配置如下:
"scripts": {
"build": "webpack --config config/webpack.prod.js",
"dev": "webpack server --config config/webpack.dev.js"
},
运行脚本,查看结果:
npm run build
npm run dev
9.创建.html文件
可以进行打包js资源之后,那么就需要创建一个
.html文件来加载打包编译后的.js文件,查看结果,在根目录下创建index.html,但是,生产环境我们往往会生成不同的hash值来防止资源缓存,所以每次生成的文件名都是不同的,手动引入入口文件往往不太现实,所以需要借助html-webpack-plugin插件来自动生成项目中的html页面,并实现自动导入对应脚本。
安装
html-webpack-plugin,并在公共的webpack配置文件中去使用此插件
// 安装
npm i html-webpack-plugin -D
// 配置
const path = require("path")
const srcPath = path.join(__dirname, "..", "src")
// 引入html-webpack-plugin
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
entry: path.join(srcPath, "index.js"),
plugins: [
new HtmlWebpackPlugin({
// 选择根目录下的index.html文件为模板文件,在dist文件夹下自动生成
// 注意,这里是相对根目录而言的,因为脚本的上下文是在根目录下
template: 'index.html'
// inject: 'head', // 脚本注入的位置,可以是head, body,或者为 false默认
// 在这里还可以自定义参数,在模板中,使用ejs方式 <%= htmlWebpackPlugin.options %>获取自定义属性
title: 'Webpack Test',
// webpack5默认开启压缩属性,webpack4要手动设置
// minify: {
// removeComments: true, // 删除注释
// collapseWhitespace: true // 删除空格
// }
})
]
}
运行
npm run build测试,dist目录下是否生成index.html文件,并且自动加载打包好的js文件.
10.clean-html-plugin删除之前的打包文件
我们在打包的过程中发现,每一次的打包,之前的文件包还是存在的,需要手动的去删除,不然影响打包文件的目录显得很乱,心里也是很难受。这个时候码农的偷懒精神就得以展现的淋漓尽致啦。使用
clean-webpack-plugin插件,可以邦族我们在每一次打包文件之前,将之前的打包的旧文件包进行删除,生成最新的打包文件;
- 安装插件:
npm i clean-webpack-plugin -D
- 在
webpack公共文件中进行配置
const path = require("path")
const srcPath = path.join(__dirname, "..", "src")
// 引入html-webpack-plugin
const HtmlWebpackPlugin = require('html-webpack-plugin')
// 引入clean-html-plugin
const { CleanWebpackPlugin } = require("clean-webpack-plugin")
module.exports = {
entry: path.join(srcPath, "index.js"),
plugins: [
new HtmlWebpackPlugin({
// 选择根目录下的index.html文件为模板文件,在dist文件夹下自动生成
// 注意,这里是相对根目录而言的,因为脚本的上下文是在根目录下
template: 'index.html',
// inject: 'head', // 脚本注入的位置,可以是head, body,或者为 false默认
// 在这里还可以自定义参数,在模板中,使用ejs方式 <%= htmlWebpackPlugin.options %>获取自定义属性
title: 'Webpack Test'
// webpack5默认开启压缩属性,webpack4要手动设置
// minify: {
// removeComments: true, // 删除注释
// collapseWhitespace: true // 删除空格
// }
}),
// 打包前删除上次的打包文件
new CleanWebpackPlugin()
]
}
到目前为止,只要是按照这个步骤一步一步进行配置的,前端的环境是完全没有问题的!
11.NODE_ENV=?配置环境的全局变量
我们通常会有个配置文件,需要根据环境的不同,配置不同的接口地址,这时一般就会用到全局变量,
webpack可以使用DefinePlugin插件来设置全局变量,我们一般在package.json文件运行脚本中,会自定义一个环境变量NODE_ENV,这个变量就可以在webpack的公共文件进行访问了process.env.NODE_ENV,但是在其他的js文件中是获取不到的,但是可以在webpack.common.js中进行配置(设置为全局变量),以后再其他的js文件中也是可以访问这个变量的:
// webpack.common.js
plugins: [
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV)
})
]
现在基本上不存在这个问题了,因为对于5来说,
mode的配置值,就是这个变量,所以利用webpack5的童鞋们就不要再配置上面的plugins了:
// mac电脑
"scripts": {
"build": "NODE_ENV=prod webpack --config config/webpack.prod.js",
"dev": "NODE_ENV=dev webpack server --config config/webpack.dev.js NODE_ENV=development"
},
// windows电脑
"scripts": {
"build": "set NODE_ENV=prod && webpack --config config/webpack.prod.js",
"dev": "set NODE_ENV=dev && webpack server --config config/webpack.dev.js NODE_ENV=development"
},
12.npm run dev开发环境的配置
在前面的时候,这个脚本是我们配置过的,
dev就是development表示的是开发环境,因为我们配置了入口html文件了,所以可以运行命令npm run dev进行启动开发的服务器,再次改变只要保存就行了,不需要一直进行编译。
1)跨域问题进行配置
在
webpack.dev.js设置devServer:
const path = require("path")
const commonConfig = require("./webpack.common.js")
const {
merge
} = require('webpack-merge')
const devConfig = {
mode: 'development',
output: {
filename: 'bunlder.js',
path: path.join(__dirname, "..", "dist")
},
devServer: {
// 设置代理
proxy: {
// 将本地默认域名localhost:8080 代理到 localhost:6666/xxx,/api2/xxx ,通常用这个,/api2仅作为代理转发的标识
'/api2': {
target: 'http://localhost:3000',
changeOrigin: true,
pathRewrite: {
// 如果带有 ^ 最终访问的路径是去除/api2的,去除代理的命名
'^/api2': ''
},
secure: false
}
}
}
}
module.exports = merge(commonConfig, devConfig)
13.样式文件.css/.less等样式文件处理
如果我们在
index.js文件通过import './style/css/index.css'样式文件时,进行webpack打包的时候会出现错误,因为啊,webpack只能认识.js文件,其他类型的文件,它是不认识的,就需要我们借助loader来处理样式类的文件,转换成js可以处理的文件。
注意:我时安装了两个
loader,但是还会进行报错,后来找到解决方案,在index.js入口文件中引入css文件时候格式须这样写:import "style-loader!css-loader!./css/index.css",就是在路径前面加上loader名称和!
1)处理.css文件
- 安装相关
loader
npm i css-loader style-loader -D
webpack.common.js文件中配置module.rules的loader处理规则
const path = require("path")
const srcPath = path.join(__dirname, "..", "src")
// 引入html-webpack-plugin
const HtmlWebpackPlugin = require('html-webpack-plugin')
// 引入clean-html-plugin
const { CleanWebpackPlugin } = require("clean-webpack-plugin")
module.exports = {
entry: path.join(srcPath, "index.js"),
plugins: [
new HtmlWebpackPlugin({
// 选择根目录下的index.html文件为模板文件,在dist文件夹下自动生成
// 注意,这里是相对根目录而言的,因为脚本的上下文是在根目录下
template: 'index.html',
// inject: 'head', // 脚本注入的位置,可以是head, body,或者为 false默认
// 在这里还可以自定义参数,在模板中,使用ejs方式 <%= htmlWebpackPlugin.options %>获取自定义属性
title: 'Webpack Test'
// webpack5默认开启压缩属性,webpack4要手动设置
// minify: {
// removeComments: true, // 删除注释
// collapseWhitespace: true // 删除空格
// }
}),
// 打包前删除上次的打包文件
new CleanWebpackPlugin()
],
// loader配置
module: {
rules: [
{
test: '/\.css$/', //匹配规则
use: ['style-loader','css-loader'] //使用的loader
}
]
}
}
2)处理.less和.scss文件和上面一样
- 安装相关
loader
npm i css-loader style-loader less-loader less -D
webpack.common.js文件中配置module.rules的loader处理规则
module: {
rules: [
{
test: '/\.css$/', //匹配规则
use: ['style-loader','css-loader'] //使用的loader
},
{
test: '/\.less$/', //匹配规则
use: ['style-loader','css-loader','less-loader'] //使用的loader
}
]
}
3)为了提高css的兼容性,适配不同的浏览器厂商,可以利用插件为css自动添加前缀
- 安装相关
loader
`npm i postcss-loader autoprefixer -D`
webpack.common.js文件中配置module.rules的loader处理规则
module: {
rules: [
{
test: /.css$/,
use: ['style-loader', 'css-loader', 'postcss-loader']
},
{
test: /.less$/,
use: ['style-loader', 'css-loader','postcss-loader', 'less-loader']
}
]
},
plugins: [
require('autoprefixer')
]
4)生产环境中将css文件进行抽离,与html文件不进行混合
- 安装相关
loader
`npm i mini-css-extract-plugin -D`
webpack.prod.js文件中配置,将前面的style-loader换成mini-css-extract-plugin的loader
const path = require('path')
const commonConfig = require('./webpack.common.js')
const {
merge
} = require('webpack-merge')
// 引入在生产环境中,将css文件进行抽离的插件: mini-css-extract-plugin
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const prodConfig = {
mode: 'production', // 生产环境
output: {
filename: 'bundle.[chunkhash].js', // 输出文件名,一般要加上hash
path: path.join(__dirname, '..', 'dist') // 输出目录
},
module: {
rules: [{
test: '/\.css$/',
use: [MiniCssExtractPlugin.loader, 'css-loader']
},
// {
// test: '/\.less$/',
// use: [MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader', 'less-loader']
// }
]
},
plugins: [
new MiniCssExtractPlugin({
filename: 'css/[name]_[contenthash].css',
chunkFilename: '[name]_[contenthash].css'
})
]
}
module.exports = merge(commonConfig, prodConfig)
在我使用这个分离插件打包的时候,没有报错,但是
css文件在打包后也是没有进行分离出来,这里算是没有成功的,后面如果成功了,就回来更新方法。
5) 图片等资源文件的处理
如果要在js中像引用其他的
.css一样,引用图片资源并容易使用(import img from './images/a.jpg'),或者在.css中设置背景图(background: url('../images/b.png'),这个时候就需要处理图片资源的loader来解决这个问题了。
目前市场上用户较多的两款
loader是:file-loader和url-loader,两款loader差不多,只是url-loader多出来一个可以设置根据文件大小来决定是否进行base6的转换的功能。
file-loader(开发环境) 1.安装:npm i file-loader -D2.webpack.dev.js配置:
// 处理css样式文件中的url图片
{
test: /.(jpg|png|jpeg|gif)$/,
use: ['file-loader']
}
url-loader(生产环境) 1.安装:npm i url-loader -D2.在webpack.dev.js和webpack.common.js配置此loader:
module: {
rules: [
{
// 正则匹配的时候,正则表达式不需要进行加上引号
test: /\.(jpg|png|jpeg|gif)$/,
use: {
loader: 'url-loader',
options: {
limit: 8192, //配置项,是限制图片如果是小于8kb的就将图片转换为base64
esModule: false,
name: '[name]_[hash:8].[ext]',
outputPath: 'images' //打包到/images目录下面
}
}
}
]
},
6)处理ES6+的代码
虽然
webpack本身就是可以处理js代码的,但是一些比较新的代码,比如ES6之上的新特性,webpack也是处理不了的,这个时候也需要特定的处理的loader来进行处理,babel-loader就是最常用的处理新特性的loader:
- 安装
loadernpm i babel-loader @babel/core @babel/preset-env -D - 配置
// babel-loader处理js
{
test: /\.js$/,
use: ['babel-loader'], //缓存
include: srcPath, // 缩小查询范围
exclude: /node_modules/ //排除要处理的文件夹
}
// 在项目的根目录创建,.babelrc
{
"presets": ["@babel/preset-env"], // 一般使用@babel/preset-env就够了
"plugins": []
}
// 对于babel版本高于v7.8.0,可以将.babelrc 变为在根目录创建 babel.config.json
{
"presets": [
[
"@babel/env",
{
"targets": {
"edge": "17",
"firefox": "60",
"chrome": "67",
"safari": "11.1"
},
"useBuiltIns": "usage",
"corejs": "3.6.5"
}
]
]
}
7)引用文件路径使用@操作符
为了更好的引用资源路径,配置路径引用还是蛮好的,配置如下:
resolve: {
alias: {
'@': path.resolve(__dirname,'./src')
}
}
以上就是最常用的项目工程化的
webpack的配置啦,如果后续有更好的配置,我会进行更新加载进来。