WebPack5 自由配置

109 阅读4分钟

webpack5是一个打包工具,可以按我们自己的方式对文件或是目录进行处理,生成我们需要的样子,如何更灵活的配置,就要先从基本的开始,然后一点点扩展

项目的目录结构

|-config
    |-base
    |-config
    |-dev
    |-pro
|-public
    |-favicon.ico
    |-index.html
|-node_modules
|-src
    |-index.js
|-package.json

1.构建基本项目

初始化package.json

npm init -y

安装webpack相关包

npm i -D webpack-dev-server webpack webpack-cli webpack-merge

webpack,webpack-cli:主要执行webpack打包命令

webpack-dev-server: 开启静态服务

webpack-merge:合并文件

验证:

src/index.js  //入口文件

const a = 10;
console.log(a)

config/base.js  //所有环境的公用配置

const path = require('path');module.exports = {    entry:{        main: './src/index.js'    },    output: {        publicPath: '/',        path: path.resolve(__dirname, '..', 'dist')    }}

config/config.js  //根据不同的环境执行不同的文件

const { merge } = require('webpack-merge');const baseConfig = require('./base');const devConfig = require('./dev');const proConfig = require('./pro');module.exports = (env, argv) => {    let config = argv.mode === 'development' ? devConfig :  proConfig;    return merge(baseConfig, config);};

config/pro.js  //这个文件是打包生产环境的配置

const path = require('path');module.exports = {    mode: 'production',};

最后我们需要配置webpack的命令

package.json 中加入如下代码

 "scripts": {    "build": "webpack --mode=production --config config/config.js"  }

那为什么这个是执行命令的呢,我们本地安装的是webpack和wenbpack-cli,webpack是打包工具,而webpack-cli提供了许多命令来使 webpack 的工作变得简单,官方也提供了命令的参数:webpack-cli,大家可以参考着进行配置

上文我们配置好之后,在终端执行npm run build 

就可以看到打包成功了,会生成dist目录

1.2.解析babel

如果项目中使用ES6+可以在webpack中进行配置

参考:babel 官网 

npm install --save-dev @babel/core @babel/cli @babel/preset-env babel-loader

安装成功后在config/base.js

  module: {        rules: [            {                test: /\.js(\?.*)?$/,                exclude: (file) => /node_modules/.test(file) && !/\.js/.test(file),                use: {                    loader: 'babel-loader'                }            }        ]    }

此时,就可以正常的编写ES6的代码了,但这个只是解析语法,对于一些类或函数,比如Promise,includes等需要引入一些辅助函数,来解决这个问题

npm i -D @babel/plugin-transform-runtime @babel/runtime-corejs3

在.babelrc中

{    "presets": ["@babel/preset-env"],    "plugins": [      [        "@babel/plugin-transform-runtime",        {          "corejs": 3,          "helpers": true,          "regenerator": true,          "useESModules": false        }      ]    ]}

@babel/preset-env 这个让我们可以使用ES6+的语法,详情参考网上配置

@babel/plugin-transform-runtime 需要搭配corejs 和这个的配置来引入相应的依赖,详情请参考这个地址

配置完成后无效,你可以试一下,那为什么?

因为我们没有配置target,也就是目标浏览器,我们需要再加入如下配置:

.browserslistrc 文件

> 1%
last 2 versions
not ie <= 10

之后就可以正常的打包运行了

1.3.webpack serve配置

其实就是nodeJs写的一个服务器,帮助我们本地开发的部署,以及代理等进行相关的配置

config/dev.js

如下进行了简单的配置

const path = require('path');const webpack = require('webpack');module.exports = {    mode: 'development',    devtool: 'eval-cheap-module-source-map',    devServer: {        // 启动devServer,不会在本地生成文件,所有文件会编译在内存中(读取速度快)        contentBase: path.join(__dirname, '../dist'), //静态文件根目录        overlay: true, // 错误信息直接显示在浏览器窗口中        port: 8888,        publicPath: '/',        inline: true, // 实时重载的脚本被插入到你的包(bundle)中,并且构建消息将会出现在浏览器控制台        host: '0.0.0.0', // 设置为0.0.0.0并配合useLocalIp可以局域网访问        useLocalIp: true, // 使用本机IP打开devServer,而不是localhost        open: 'chrome',//使用谷歌浏览器打开项目    },};

然后再packge.json中加入

 "scripts": {    "start": "webpack serve --mode=development --config config/config.js",    "build": "webpack --mode=production --config config/config.js"  },

启动 npm start

再在config/base.js中加入

  plugins:[        new HtmlWebpackPlugin({            template: path.join(__dirname, '../public/index.html'),            favicon: path.join(__dirname, '../public/favicon.ico'), //favicon路径            filename: 'index.html',            chunks: ['main'],            inject: true,            minify: true,            cache: false,            hash: true //开启hash  ?[hash]        }),    ]

可以看到成功运行起来了,

注意:webpack5中,webpack-dev-server  使用webpack serve来启动webpack-dev-server服务器

1.4.热更新

在章节三中,我们似乎加了热更新,但并没有效果,为什么?

我们在src/index.js中加入如下代码,每次更新sum的参数,可以看到控制台并没有打印出相应的值,只有手动刷新值才会变更,为什么呢?

const sum = (a,b) => a+b;console.log(sum(1,2))

在devServer中我们加入了hot: true,而且webpack5在中是不需plugins: [new webpack.HotModuleReplacementPlugin()],,不信加进去也没有效果

后来参考资料说是target的问题就测试了一下:

官方说:tagert告知 webpack 为目标(target)指定一个环境。默认值为 "browserslist",如果没有找到 browserslist 的配置,则默认为 "web"

然后我们本地packge.json中加入了“browserslist”,但依然是没有效果的,后来换成了“web”,就可以正常的热更新了

    target:"web",
    devServer:{         hot: true, //完成HMR
   }

JS热更新完成了,但是css呢找官方文档:地址

webpack文档上说需要使用style-loader去使热更新生效,我们试一下

npm install --save-dev style-loader css-loader

注意:如果只使用css-loader是没有效果的

在src/index.js中加入

import "./styles/index.css"

然后再config/base.js中加入如下配置:

  {    test: /\.css$/,          
       use: ['style-loader', 'css-loader'],  
 },

可以试一下,改变背景色,颜色值也会立即改变

这样样式和JS的热更新就完成了,这个是基本的配置,我么使用这个可以做除了使用Jquery或是其它库来编写代码

1.5.打包

打包很简单

在config/pro中加入如下代码:就可以完成打包了,为什么,因为webpack帮你进行了默认配置

const path = require('path');module.exports = {    mode: 'production',};

1.6.清除上次构建的文件

clean-webpack-plugin:

帮助你对每次打包命令执行的时候自动清除dist文件夹,不需要每次手动去删除

在config/pro.js中

const { CleanWebpackPlugin } = require('clean-webpack-plugin');

 plugins:[        new CleanWebpackPlugin() ]

这样基本的打包功能就实现了,这个只是初始的模型,后续我们添加一些loader和插件来帮助我们来完善这个功能,下一章节则讲解常用的loader

2.常用Loader

对文件的预处理,按自己的需求将文件加工好后再返回来

2.1 样式处理loader

* style-loader 将模块导出的内容作为样式并添加到 DOM 中

我们一sass 为例进行配置

先安装如下

npm i -D  sass-loader sass dart-sass

在config/base.js中进行配置

  {                test: /\.css$/,                use: [                    'style-loader',                     'css-loader'                ]            },            {                test: /\.scss$/,                use: [                    'style-loader',                    'css-loader',                    'sass-loader'                ]            }

安装完成后在config/base.js中加入配置,并在styles/index.scss 和styles/index.css 来添加一些样式,如下样式都生效了,说名对scss和css文件的解析成功了

但这个时候文件是在index.html中的style中的,我想将它导出成文件可以使用mini-css-extract-plugin

简单配置:

config/base.js

  {                test: /\.css$/,                use: [                    MiniCssExtractPlugin.loader,                     'css-loader'                ]            },            {                test: /\.scss$/,                use: [                    MiniCssExtractPlugin.loader,                    'css-loader',                    'sass-loader'                ]            }
 plugins:[        new MiniCssExtractPlugin(),
]

打包之后就会多了个main.css文件出来,当前你也可以根据环境来判断具体应该适应style-loader还是MiniCssExtractPlugin.loader,具体请参考我的github

2.2加载资源文件

需要使用file-loader和url-loader 

  {                test: /\.(|woff|woff2|ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,                use: [                    {                        loader: 'file-loader',                        options: {                            esModule: false,                            limit: 2048,                            name: 'assets/fonts/[name].[ext]',                            publicPath: '/'                        }                    }                ]            },            {                test: /\.(png|jpg|gif|svg|ico)$/i, //正则表达式匹配图片规则                use: [                    {                        loader: 'url-loader',                        options: {                            esModule: false,                            limit: 2048,                            name: 'assets/images/[name].[ext]', //images:图片打包的文件夹;                            publicPath: '/'                        }                    }                ]            }

这个主要是对图片和字体的处理

这个只是配置的基础,后续会陆续进行扩展,比如如何使用cssmodule ,如何配置多环境,如何配置vue 的eslint以及单元测试配置等