Skip to content

Webpack 工程实践 ​

多页面配置 ​

js
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
  mode: 'development',
  entry: {
    home: './src/index.js',
    other: './src/other.js',
  },
  output: {
    filename: '[name].js', // [name] 代表 home 或 other
    path: path.resolve(__dirname, 'dist'),
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './index.html',
      filename: 'home.html',
      chunks: ['home'],
    }),
    new HtmlWebpackPlugin({
      template: './index.html',
      filename: 'other.html',
      chunks: ['other'],
    }),
  ],
}
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
  mode: 'development',
  entry: {
    home: './src/index.js',
    other: './src/other.js',
  },
  output: {
    filename: '[name].js', // [name] 代表 home 或 other
    path: path.resolve(__dirname, 'dist'),
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './index.html',
      filename: 'home.html',
      chunks: ['home'],
    }),
    new HtmlWebpackPlugin({
      template: './index.html',
      filename: 'other.html',
      chunks: ['other'],
    }),
  ],
}

Source Map ​

js
module.exports = {
  // 1) 源码映射,生成单独 sourcemap 文件,标识报错列和行
  // devtool: 'source-map'

  // 2) 不产生单独文件,显示报错的列和行,集成到 JS 中
  // devtool: 'eval-source-map'

  // 3) 不产生列,生成单独映射文件
  // devtool: 'cheap-module-source-map'

  // 4) 不产生文件,集成在打包文件中,不产生列
  devtool: 'cheap-module-eval-source-map',
}
module.exports = {
  // 1) 源码映射,生成单独 sourcemap 文件,标识报错列和行
  // devtool: 'source-map'

  // 2) 不产生单独文件,显示报错的列和行,集成到 JS 中
  // devtool: 'eval-source-map'

  // 3) 不产生列,生成单独映射文件
  // devtool: 'cheap-module-source-map'

  // 4) 不产生文件,集成在打包文件中,不产生列
  devtool: 'cheap-module-eval-source-map',
}

Watch 模式(实时打包) ​

js
module.exports = {
  watch: true,
  watchOptions: {
    poll: 1000, // 每秒检查 1000 次
    aggregateTimeout: 500, // 防抖,500ms 内只打包一次
    ignored: /node_modules/,
  },
}
module.exports = {
  watch: true,
  watchOptions: {
    poll: 1000, // 每秒检查 1000 次
    aggregateTimeout: 500, // 防抖,500ms 内只打包一次
    ignored: /node_modules/,
  },
}

常用插件 ​

CleanWebpackPlugin(打包前清理目录) ​

bash
yarn add clean-webpack-plugin -D
yarn add clean-webpack-plugin -D
js
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
module.exports = {
  plugins: [new CleanWebpackPlugin()],
}
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
module.exports = {
  plugins: [new CleanWebpackPlugin()],
}

CopyWebpackPlugin(拷贝文件到 dist) ​

bash
yarn add copy-webpack-plugin -D
yarn add copy-webpack-plugin -D
js
const CopyWebpackPlugin = require('copy-webpack-plugin')
module.exports = {
  plugins: [
    new CopyWebpackPlugin([{ from: './doc', to: './' }]),
  ],
}
const CopyWebpackPlugin = require('copy-webpack-plugin')
module.exports = {
  plugins: [
    new CopyWebpackPlugin([{ from: './doc', to: './' }]),
  ],
}

BannerPlugin(版权声明,webpack 内置) ​

在每个 JS 文件开头添加注释:

js
const webpack = require('webpack')
module.exports = {
  plugins: [new webpack.BannerPlugin('make hny 2019/12/05')],
}
const webpack = require('webpack')
module.exports = {
  plugins: [new webpack.BannerPlugin('make hny 2019/12/05')],
}

Webpack 跨域问题 ​

devServer 代理 ​

js
module.exports = {
  devServer: {
    // 方式1:代理到另一个端口
    proxy: {
      '/api': {
        target: 'http://localhost:3000',
        pathRewrite: { '/api': '' },
      },
    },
    // 方式2:在 before 钩子中模拟数据
    before(app) {
      app.get('/user', (req, res) => {
        res.json({ name: 'hny' })
      })
    },
  },
}
module.exports = {
  devServer: {
    // 方式1:代理到另一个端口
    proxy: {
      '/api': {
        target: 'http://localhost:3000',
        pathRewrite: { '/api': '' },
      },
    },
    // 方式2:在 before 钩子中模拟数据
    before(app) {
      app.get('/user', (req, res) => {
        res.json({ name: 'hny' })
      })
    },
  },
}

webpack-dev-middleware(服务端启动 webpack) ​

前后端开发到一起,请求数据不存在跨域问题:

bash
yarn add webpack-dev-middleware -D
yarn add webpack-dev-middleware -D
js
// server.js
const express = require('express')
const webpack = require('webpack')
const middle = require('webpack-dev-middleware')
const config = require('./webpack.config.js')
const compiler = webpack(config)

const app = express()
app.use(middle(compiler))

app.get('/user', (req, res) => { res.json({ name: 'hny' }) })
app.listen(3000)
// server.js
const express = require('express')
const webpack = require('webpack')
const middle = require('webpack-dev-middleware')
const config = require('./webpack.config.js')
const compiler = webpack(config)

const app = express()
app.use(middle(compiler))

app.get('/user', (req, res) => { res.json({ name: 'hny' }) })
app.listen(3000)

运行 node server.js 同时启动 webpack 和接口服务。

DefinePlugin(定义环境变量) ​

webpack 内置插件,可在项目中直接使用:

js
module.exports = {
  plugins: [
    new webpack.DefinePlugin({
      DEV: JSON.stringify('production'),
      FLAG: 'true',
    }),
  ],
}
// 项目中使用:
// if (DEV) { url = 'http://localhost:3000' }
module.exports = {
  plugins: [
    new webpack.DefinePlugin({
      DEV: JSON.stringify('production'),
      FLAG: 'true',
    }),
  ],
}
// 项目中使用:
// if (DEV) { url = 'http://localhost:3000' }

WebpackMerge(分环境配置) ​

bash
yarn add webpack-merge -D
yarn add webpack-merge -D
js
// webpack.base.js - 公共配置
// webpack.prod.js
const { merge } = require('webpack-merge')
const base = require('./webpack.base.js')
module.exports = merge(base, { mode: 'production' })

// webpack.dev.js
module.exports = merge(base, { mode: 'development' })
// webpack.base.js - 公共配置
// webpack.prod.js
const { merge } = require('webpack-merge')
const base = require('./webpack.base.js')
module.exports = merge(base, { mode: 'production' })

// webpack.dev.js
module.exports = merge(base, { mode: 'development' })
json
"scripts": {
  "start": "webpack --config webpack.dev.js"
}
"scripts": {
  "start": "webpack --config webpack.dev.js"
}

Cross-env(运行时环境变量) ​

bash
npm install cross-env
npm install cross-env
json
"scripts": {
  "start": "cross-env NODE_ENV=development webpack"
}
"scripts": {
  "start": "cross-env NODE_ENV=development webpack"
}
js
// 取环境变量
process.env.NODE_ENV
// 取环境变量
process.env.NODE_ENV

Externals(避免打包第三方库) ​

当使用 CDN 引入时,可通过 externals 避免重复打包:

js
module.exports = {
  externals: {
    jquery: '$',
  },
}
module.exports = {
  externals: {
    jquery: '$',
  },
}