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
文件。