生产环境与开发环境的不同

相比于开发环境,生产环境需要额外考虑以下几个方面:

  1. 样式文件需要单独抽取
  2. css 兼容性处理
  3. css / js / html 文件压缩
  4. js 风格检查
  5. js 兼容性处理

一个典型的生产环境配置如下

  1. const {resolve} = require('path') // path 属于 node.js 的自带模块
  2. const MiniCssExtractPlugin = require('mini-css-extract-plugin')
  3. const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin')
  4. const HtmlWebpackPlugin = require('html-webpack-plugin')
  5. // 定义node.js的环境变量,决定使用browserslist的哪个环境
  6. process.env.NODE_ENV = 'production'
  7. const commonCssLoader = [
  8. // 这个loader取代style-loader。作用:提取js中的css成单独文件然后通过link加载
  9. MiniCssExtractPlugin.loader,
  10. // css-loader:将css文件整合到js文件中
  11. 'css-loader',
  12. /*
  13. postcss-loader:css兼容性处理:postcss --> 需要安装:postcss-loader postcss-preset-env
  14. postcss需要通过package.json中browserslist里面的配置加载指定的css兼容性样式
  15. 在package.json中定义browserslist:
  16. "browserslist": {
  17. // 开发环境 --> 设置node环境变量:process.env.NODE_ENV = development
  18. "development": [ // 只需要可以运行即可
  19. "last 1 chrome version",
  20. "last 1 firefox version",
  21. "last 1 safari version"
  22. ],
  23. // 生产环境。默认是生产环境
  24. "production": [ // 需要满足绝大多数浏览器的兼容
  25. ">0.2%",
  26. "not dead",
  27. "not op_mini all"
  28. ]
  29. },
  30. */
  31. {
  32. loader: 'postcss-loader',
  33. options: {
  34. postcssOptions: {
  35. plugins: [
  36. [
  37. 'postcss-preset-env',
  38. {
  39. ident: "postcss"
  40. },
  41. ],
  42. ],
  43. },
  44. },
  45. },
  46. ]
  47. module.exports = {
  48. entry:'./src/js/index.js',
  49. output: {
  50. filename: 'js/built.js',
  51. path: resolve(__dirname, 'build')
  52. },
  53. module: {
  54. rules:[
  55. {
  56. test: /\.css/,
  57. use: commonCssLoader,
  58. },
  59. {
  60. test: /\.less/,
  61. use:[ ...commonCssLoader, 'less-loader']
  62. },
  63. /*
  64. 正常来讲,一个文件只能被一个loader处理
  65. 当一个文件要被多个loader处理,那么一定要指定loader执行的先后顺序
  66. 先执行eslint再执行babel(用enforce)
  67. */
  68. {
  69. test: /\.js$/,
  70. exclude: /node_modules/, // 忽略node_modules
  71. enforce: 'pre', // 优先执行
  72. loader: 'eslint-loader',
  73. options: {
  74. // 自动修复
  75. fix: true,
  76. },
  77. },
  78. /*
  79. js兼容性处理:需要下载 babel-loader @babel/core
  80. 1. 基本js兼容性处理 --> @babel/preset-env
  81. 问题:只能转换基本语法,如promise高级语法不能转换
  82. 2. 全部js兼容性处理 --> @babel/polyfill
  83. 问题:只要解决部分兼容性问题,但是将所有兼容性代码全部引入,体积太大了
  84. 3. 需要做兼容性处理的就做:按需加载
  85. */
  86. {
  87. // 第三种方式:按需加载
  88. test: /\.js$/,
  89. exclude: /node_modules/,
  90. loader: 'babel-loader',
  91. options: {
  92. // 预设:指示babel做怎样的兼容性处理
  93. presets: [
  94. [
  95. '@babel/preset-env', // 基本预设
  96. {
  97. useBuiltIns: 'usage', // polyfill 按需加载
  98. corejs: { version: 3 }, // 指定core-js版本
  99. targets: { // 指定兼容到什么版本的浏览器
  100. chrome: '60',
  101. firefox: '50',
  102. ie: '9',
  103. safari: '10',
  104. edge: '17'
  105. },
  106. }
  107. ]
  108. ],
  109. },
  110. },
  111. {
  112. // 图片处理
  113. test: /\.(jpg|png|gif)/,
  114. loader: 'url-loader',
  115. options: {
  116. limit: 8 * 1024,
  117. name: '[hash:10].[ext]',
  118. outputPath: 'imgs',
  119. esModule: false, // 关闭url-loader默认使用的es6模块化解析
  120. },
  121. },
  122. {
  123. test: /\.html$/,
  124. loader: 'html-withimg-loader',
  125. // 处理html文件的img图片(负责引入img,从而能被url-loader进行处理)
  126. // url-loader esModule:false 保证用commonjs解析
  127. },
  128. // 处理其他文件
  129. {
  130. exclude: /\.(js|css|less|html|jpg|png|gif)/,
  131. loader: 'file-loader',
  132. options: {
  133. outputPath: 'media',
  134. },
  135. },
  136. ]
  137. },
  138. plugins: [
  139. new MiniCssExtractPlugin({ // 抽取单独的 css
  140. filename: 'css/built.css'
  141. }),
  142. // 压缩css
  143. new OptimizeCssAssetsWebpackPlugin(),
  144. new HtmlWebpackPlugin({
  145. template: './src/index.html',
  146. // 根据template指定的html文件,将打包后的js引入
  147. // 压缩html代码
  148. minify: {
  149. // 移除空格
  150. collapseWhitespace: true,
  151. // 移除注释
  152. removeComments: true,
  153. },
  154. })
  155. ],
  156. mode: 'production'
  157. }

样式文件单独抽取

css-loader 加载样式文件并以字符串的形式存储在js里,开发环境中使用 style-loader ,将js中的样式变成 style 标签插入页面,此种方式会导致:

  1. js 文件体积过大
  2. 先加载js,再创建style标签,渲染速度慢

生产环境使用 mini-css-extract-plugin 插件将css单独抽取成一个文件通过 link 方式引入页面,
使用时:

  1. 安装,引入插件 const MiniCssExtractPlugin = require('mini-css-extract-plugin')
  2. plugin 配置插件初始化
  3. MiniCssExtractPlugin.loader 取代 style-loader

    css 兼容性处理

    postcss-loader 用来进行 css 兼容性处理,需要安装 postcss-loaderpostcss-preset-env ,css 兼容性和浏览器的版本有关,postcss 需要通过 package.json 里面的 browserslist 来指定兼容的浏览器版本
    1. // package.json
    2. {
    3. "browserslist": {
    4. // 开发环境 --> 设置node环境变量:process.env.NODE_ENV = development
    5. "development": [ // 开发环境,不需要兼容太多
    6. "last 1 chrome version",
    7. "last 1 firefox version",
    8. "last 1 safari version"
    9. ],
    10. "production": [ // 生产环境,需要兼容大部分常见浏览器
    11. ">0.2%",
    12. "not dead",
    13. "not op_mini all"
    14. ]
    15. },
    16. }
    postcss-loader 可以和 css-loader , MiniCssExtractPlugin.loader 一起作为处理 css 的组合
    1. const commonCssLoader = [
    2. // 这个loader取代style-loader。作用:提取js中的css成单独文件然后通过link加载
    3. MiniCssExtractPlugin.loader,
    4. // css-loader:将css文件整合到js文件中
    5. 'css-loader',
    6. {
    7. loader: 'postcss-loader',
    8. options: {
    9. postcssOptions: {
    10. plugins: [
    11. [
    12. 'postcss-preset-env',
    13. {
    14. ident: "postcss"
    15. },
    16. ],
    17. ],
    18. },
    19. },
    20. },
    21. ]

    html / css / js 文件压缩

    html压缩

    配置 HtmlWebpackPluginminify

    css 压缩

    初始化 OptimizeCssAssetsWebpackPlugin

    js 压缩

    mode = production 生产环境自动压缩

    js 风格检查

    eslint-loader 对 js 进行风格检查,注意忽略 node_modules 文件夹,而且在加载 js 的时候是最先执行的 enforce: pre

    js 兼容性处理

    babel-loader 需要配置 @babel/preset-env 转换基本语法,剩下的高级语法需要配置 @babel/polyfill