Webpack项目打包配置案例


webpack依赖安装

npm i -D webpack@4 webpack-cli@3  
# 安装webpack4版本  
# 安装webpack-cli3版本 此工具用于在命令行中运行 webpack  
  
npm i -D clean-webpack-plugin  
# 常用插件,打包前自动清理之前打包的文件  
  
npm i -D webpack-node-externals  
# 打包时排除node_modules,里面的所有依赖都不打包  
  
npm i -D @babel/core @babel/node @babel/preset-env babel-loader  
# 使用es6语法所需的babel相关依赖  
# @babel/node在babel7中被移了出来,如果在node环境中使用,要单独安装,有在运行Babel预设和插件之前进行编译的好处,调试用  
  
npm i -D terser-webpack-plugin@4  
# 生产环境需要打包压缩代码  
  
npm i -D webpack-merge  
# 分开发配置和生产配置,它们有共同配置,抽离出来,通过webpack-merge合并  
  
npm i -D nodemon  
# 监控node.js 源代码的变化和自动重启服务  
  
npm i -D cross-env  
# 运行跨平台设置和使用环境变量的脚本  
  
npm i -D npm-run-all  
# 实现同时执行多个命令  
  
npm i -D rimraf  
# 以包的形式包装rm -rf命令,用来删除文件和文件夹的。用来清理dist目录

配置文件

webpack可指定多个配置文件,用于区分开发与生产环境打包配置

  • webpack.config.base:存放通用配置
  • webpack.config.dev:存放开发环境专项配置
  • webpack.config.prod:存放生产环境专项配置
const path = require('path')  
const webpack = require('webpack')  
const nodeExternals = require('webpack-node-externals')  
const { CleanWebpackPlugin } = require('clean-webpack-plugin')  
  
const webpackConfig = {  
 target: 'node', // koa项目仅在node环境下运行,因此设置称'node'  
 entry: {  
 // 设置入口文件  
 server: path.join(__dirname, '../src/index.js')  
 },  
 output: {  
 // 设置打包后的文件和位置  
 filename: '[name].bundle.js',  
 path: path.join(__dirname, '../dist')  
 },  
 module: {  
 rules: [  
 {  
 test: /\.js|jsx$/,  
 use: {  
 loader: 'babel-loader'  
 },  
 // 尽量将 loader 应用于最少数量的必要模块,因此设置include  
 // 只针对该目录下的js文件进行babel处理  
 include: path.join(__dirname, '../src')  
 }  
 ]  
 },  
 resolve: {  
 // modules: 告诉webpack哪些目录需要搜索去匹配解析  
 modules: [path.join(__dirname, '../src/index.js'), 'node_modules'],  
 // extensions: 告诉webpack这些后缀文件需要去搜索匹配  
 extensions: ['.js', '.json'],  
 alias: {  
 // 设置别名指向对应目录  
 '@': path.join(__dirname, '../src')  
 }  
 },  
 externals: [nodeExternals()], // 排除对node_modules里的依赖进行打包  
 plugins: [  
 new CleanWebpackPlugin(), // 打包前清除输出目录  
 new webpack.DefinePlugin({  
 // 定义环境变量,区分开发和生产环境  
 // 具体详情可查看DefinePlugin文档  
 'process.env.NODE_ENV':  
 process.env.NODE_ENV === 'production'  
 ? JSON.stringify('production')  
 : JSON.stringify('development')  
 })  
 ],   
}  
  
module.exports = webpackConfig

开发环境配置:

const { merge } = require('webpack-merge')  
const baseConfig = require('./webpack.config.base')  
  
// 通过webpack-merge合并基础配置,添加开发时配置  
const webpackConfig = merge(baseConfig, {  
 mode: 'development', // 开发模式  
 devtool: 'eval-source-map', // 开发时出错能知道在源代码中哪一行  
 stats: {  
 children: false, // webpack打包时子模块信息设置不显示  
 modules: false // 不显示模块信息  
 }  
})  
  
module.exports = webpackConfig

生产环境配置

const { merge } = require('webpack-merge')  
const baseConfig = require('./webpack.config.base')  
const TerserPlugin = require('terser-webpack-plugin')  
  
// 通过webpack-merge合并基础配置,添加生产时配置  
const webpackConfig = merge(baseConfig, {  
 mode: 'production', // 生产模式  
 stats: {  
 children: false, // webpack打包时子模块信息设置不显示  
 warnings: false // 警告不显示  
 },  
 optimization: {  
 minimizer: [  
 // terser-webpack-plugin插件可以压缩代码  
 // 在webpack4版本中需要安装terser-webpack-plugin4版本  
 // 里面是官方推荐的具体的参数,详情可查看文档  
 new TerserPlugin({  
 terserOptions: {  
 warning: true,  
 compress: {  
 warnings: false,  
 drop_console: false, // 取消注释console 方便有时候进行调试  
 dead_code: true,  
 drop_debugger: true  
 },  
 output: {  
 comments: false, // 不要注释  
 beautify: false // 不要格式,一行显示所有代码  
 },  
 mangle: true  
 },  
 parallel: true, // 使用多进程并行运行可提高构建速度,默认的并发运行数量 os.cpus().length - 1  
 sourceMap: false  
 })  
 ],  
 // splitChunks 用来避免模块之间重复的依赖关系  
 splitChunks: {  
 cacheGroups: {  
 commons: {  
 name: 'commons',  
 chunks: 'initial',  
 minChunks: 3,  
 enforce: true  
 }  
 }  
 }  
 }  
})  
  
module.exports = webpackConfig

es6语法支持

在项目根目录创建配置文件.babelrc

{  
 "presets": [  
 [  
 "@babel/preset-env",  
 {  
 "targets": {  
 "node": "current"  
 }  
 }  
 ]  
 ]  
}

如果我们用node src/index.js去运行,报错:

import Koa from 'koa'  
^^^^^^  
  
SyntaxError: Cannot use import statement outside a module

在在安装babel之后,node_modules中提供了一个babel-node命令,我们可以通过该命令来运行我们的入口文件。
npx babel-node src/index.js

配合之前安装的nodemon可以实现热更新
npx nodemon --exec babel-node src/index.js

可将该命令添加至webpack快捷命令中:

{  
 "script": {  
 "start": "nodemon --exec babel-node src/index.js"  
 }  
}

这样通过在终端里运行npm run start即可启动项目了。

当然这个只是简单的实现去支持es6语法和开发时热更新功能,并没有通过用webpack去构建,在项目简单的情况下尚可

webpack构建开发环境

通过webpack --watch命令来监听项目中文件的变化,如果其中一个文件被更新,代码将被重新编译,而不必再去手动运行整个构建。

同时我们通过cross-env来设置环境变量,来指定当当前开发环境还是生产环境。

npx cross-env NODE_ENV=development webpack --watch --config config/webpack.config.dev.js --progress

执行该命令的意思就是,设置一个环境变量NODE_ENV,值为development,因为我们之前在配置文件中通过DefinePlugin做了配置,所以当这个值不是production时就是开发环境,定义了对应的变量,在项目文件中就可以拿到这个变量,来针对开发和生产时做不同的逻辑处理。

设置了开发时的环境变量后,通过webpack --watch启动监听模式,指定开发时的配置文件config/webpack.config.dev.js文件,当项目中文件发生变化,代码将被重新编译打包输出到dist/server.bundle.js

此时可更新配置文件:

{  
 "script": {  
 "start": "nodemon --exec babel-node src/index.js",  
 "webpack:debug": "node --inspect-brk ./node_modules/.bin/webpack --config config/webpack.config.prod.js --progress",  
 "watch": "cross-env NODE_ENV=development webpack --watch --config config/webpack.config.dev.js --progress",  
 "debug": "nodemon --inspect dist/server.bundle.js"  
 }  
}

一个终端控制台只能监听一个命令,如果每次启动项目都开两个终端比较麻烦,所以我们安装一个工具npm-run-all,来实现一个脚本同时执行多个命令。继续在package.json中添加脚本:

{  
 "script": {  
 "start": "nodemon --exec babel-node src/index.js",  
 "webpack:debug": "node --inspect-brk ./node_modules/.bin/webpack --config config/webpack.config.prod.js --progress",  
 "watch": "cross-env NODE_ENV=development webpack --watch --config config/webpack.config.dev.js --progress",  
 "debug": "nodemon --inspect dist/server.bundle.js",  
 "start:dist": "npm-run-all -p watch debug"  
 "build": "cross-env NODE_ENV=production webpack --config config/webpack.config.prod.js"
 }  
}

npm-run-all -p watch debug命令的含义是并行执行watch和debug两个脚本命令-p是并行执行的意思。

配置eslint + prettier风格

安装eslint

# 安装eslint  
npm i eslint -D  
  
# eslint初始化  
npx eslint --init  
  
# 进入自定义选择项  
# 1. 你想要怎么使用eslint? To check syntax and find problems  
# 2. 哪一种模块是你的项目使用的? JavaScript modules  
# 3. 选择哪一个框架? None of these  
# 4. 你想要使用TypeScript吗? N  
# 5. 你要运行在哪个环境? Browser, Node  
# 6. 你想要配置文件格式是哪个? JavaScript  
  
# 全部选择完成后,会在本地生成.eslintrc.js文件

安装prettier

# 安装相关配置依赖  
npm install --save-dev eslint-config-prettier  
npm install --save-dev eslint-plugin-prettier  
npm install --save-dev --save-exact prettier

然后在.eslintrc.js文件中添加配置:

module.exports = {  
 ...  
 plugins: ['prettier'],  
 extends: ['eslint:recommended', 'prettier', 'prettier/prettier'],  
 rules: {  
 'prettier/prettier': 'error'  
 }  
}

具体的prettier规则可以新建一个.prettierrc文件设置。

{  
  "singleQuote": true,  
 "trailingComma": "es5",  
 "printWidth": 100,  
 "semi": false,  
 "jsxSingleQuote": true,  
 "prettier.eslintIntegration": true  
}

另外为了增加验证效率,排除那些不需要验证规则的文件,比如mode_modules,可以新建.eslintignore.prettierignore文件。


文章作者: Semon
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Semon !
评论
  目录