webpack(三)

205 阅读2分钟
22.Weppack生产环境优化

模式mode

为不同工作环境创建不同配置

  • 配置文件根据环境不同导出不同配置
  • 一个环境对应一个配置文件

yarn webpack

yarn webpack --env production

const webpack = require('webpack')

const path = require('path')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const { compilation } = require('webpack')

class MyPlugin {
  apply(compiler) {
    console.log('MyPlugin run')
    compiler.hooks.emit.tap('MyPlugin', compilation => {
      for (const name in compilation.assets) {
        // console.log(name)
        // console.log(compilation.assets[name].source())
        if (name.endsWith('.js')) {
          const contents = compilation.assets[name].source()
          // 替换代码中的注释
          const withoutComments = contents.replace(//**+*//g, '')
          // 覆盖原有内容
          compilation.assets[name] = {
            source: () => withoutComments,
            size: () => withoutComments.length
          }
        }
      }
    })
  }
}

module.exports = (env, argv) => {
  const config = {
    mode: 'none',
    entry: './src/main.js',
    output: {
      filename: 'bundle.js',
      path: path.join(__dirname, 'dist'),
      // publicPath: 'dist/'
    },
    devServer: {
      contentBase: '/public',
      // http://localhost:8080/api/users   ---> https://api.github.com/api/users
      proxy: {
        '/api': {
          target: 'https://api.github.com',
          // http://localhost:8080/api/users   ---> https://api.github.com/users
          pathRewrite: {
            '^api': ''
          },
          // 不能使用 localhost:8080 作为请求 GitHub 的主机名
          changeOrigin: true
        },
      },
      hot: true
      // hotOnly: true // 只使用 HMR,不会 fallback 到 live reloading
    },
    devtool: 'source-map',
    module: {
      rules: [  // 其他模块加载规则
        {
          test: /.js$/,
          use: {
            loader: 'babel-loader',
            options: {
              presets: ['@babel/preset-env']
            }
          }
        },
        {
          test: /.css$/,
          use: [
            'style-loader',
            'css-loader'
          ]
        },
        //   {
        //     test: /.png$/,
        //     use:'file-loader'
        //   }
        {
          test: /.png$/,
          use: {
            loader: 'url-loader',
            options: {
              limit: 10 * 1024,   // 10kb以下文件采用url-loader超出采用file-loader
              esModule: false,   // 打包图片object%20Module
            }
          }
        },
        {
          test: /.html$/,
          use: {
            loader: 'html-loader'
          }
        }
      ]
    },
    plugins: [
      // 用于生成 index.html
      new HtmlWebpackPlugin({
        title: 'Webpack Plugin Sample',   // 设置标题
        meta: {
          viewport: 'width=device-width'
        },
        template: './index.html'  // 生成html的模板
      }),
      // 用于生成 about.html
      new HtmlWebpackPlugin({
        filename: 'about.html'
      }),
      new MyPlugin(),
      new webpack.HotModuleReplacementPlugin()
    ]
  }

  if (env === 'production') {
    config.mode = 'production'
    config.devtool = false
    config.plugins = [
      ..config.plugins,
      new CleanWebpackPlugin(),
      new CopyWebpackPlugin([
        // public/** public下的文件会拷贝到dist
        'public'
      ]),
    ]
  }
  return config
}
23.多配置文件

yarn webpack --config webpack.prod.js

yarn webpack --config webpack.dev.js

"scripts": {
  "build": "webpack --config webpack.prod.js --watch"
}

webpack.common.js

const path = require('path')

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

module.exports = {
  mode: 'none',
  entry: './src/main.js',
  output: {
    filename: 'bundle.js',
    path: path.join(__dirname, 'dist'),
    // publicPath: 'dist/'
  },
  devServer: {
    contentBase: '/public',
    // http://localhost:8080/api/users   ---> https://api.github.com/api/users
    proxy: {
      '/api': {
        target: 'https://api.github.com',
        // http://localhost:8080/api/users   ---> https://api.github.com/users
        pathRewrite: {
            '^api': ''
        },
        // 不能使用 localhost:8080 作为请求 GitHub 的主机名
        changeOrigin: true
      },
    },
    hot: true
    // hotOnly: true // 只使用 HMR,不会 fallback 到 live reloading
  },
  devtool: 'source-map',
  module: {
    rules: [  // 其他模块加载规则
      {
        test: /.js$/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env']
          }
        }
      },
      {
        test: /.css$/,
        use: [
          'style-loader',
          'css-loader'
        ]
      },
      //   {
      //     test: /.png$/,
      //     use:'file-loader'
      //   }
      {
        test: /.png$/,
        use: {
          loader: 'url-loader',
          options: {
            limit: 10 * 1024,   // 10kb以下文件采用url-loader超出采用file-loader
            esModule: false,   // 打包图片object%20Module
          }
        }
      },
      {
        test: /.html$/,
        use: {
            loader: 'html-loader'
        }
      }
    ]
  },
  plugins: [
    // 用于生成 index.html
    new HtmlWebpackPlugin({
      title: 'Webpack Plugin Sample',   // 设置标题
      meta: {
        viewport: 'width=device-width'
      },
      template: './index.html'  // 生成html的模板
    }),
    // 用于生成 about.html
    new HtmlWebpackPlugin({
      filename: 'about.html'
    })
  ]
}

webpack.dev.js

yarn add webpack-merge --dev

const common = require('./webpack.common')
const { merge } = require('webpack-merge')
const webpack = require('webpack')

module.exports = merge(common, {
  mode: 'production',
  plugins: [
    new webpack.HotModuleReplacementPlugin()
  ]
})

webpack.prod.js

const common = require('./webpack.common')
const { merge } = require('webpack-merge')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin')

module.exports = merge(common, {
 mode: 'production',
 plugins: [
   new CleanWebpackPlugin(),
   new CopyWebpackPlugin(['public'])
 ]
})
24.DefinePlugin

为代码注入全局成员

const webpack = require('webpack')
plugins: [
  new webpack.DefinePlugin({
    // 值要求的是一个代码片段
    API_BASE_URL: JSON.stringify('https://api.example.com')
    // API_BASE_URL: '*http://api.example.com*'  // api服务地址
  })
]
25.Tree-shaking

【摇掉】代码中未引用的部分

未引用代码(dead-code)

生产模式自动开启

一组功能搭配后的使用效果

optimization: {
  usedExports: true,  // 只导出外部使用的成员
  minimize: true // 压缩
}
26.合并模块(Scope Hoisting)
optimization: {
 usedExports: true,  // 只导出外部使用的成员
 concatenateModules:true, // 合并模块
 minimize: true // 压缩
}
27.Webpack Tree Shaking 与 Babel

Webpack Tree Shaking使用ESM

Babel转成CommonJS

最新版本的webpack不会让ESM实效

presets: [
  ['@babel/preset-env', { modules: 'commonjs' }]
]

presets: [
  ['@babel/preset-env', { modules: false }]
]
28.Webpack sideEffects
// package.json
"sideEffects": [
    "./src/extend.js",
    "./src/global.css"
  ]
29.Webpack 代码分割

并不是每个模块在启动时都需要

分包,按需加载(Code Splitting)

HTTP1.1缺点

同域并行请求限制

每次请求都会有一定的延迟

请求的Header浪费带宽流量