webpack4 代碼去重,簡化信息和構建優化(五)

前言

之前一段時間工作原因把精力都放在小程序上,趁現在有點空閑時間,剛好官方文檔也補充完整了,我準備重溫一下 webpack 之路了,因為官方文檔已經寫得非常詳細,我會大量引用原文描述,主要重點放在怎么從零構建 webpack4 代碼上,這不是一個系統的教程,而是從零摸索一步步搭建起來的筆記,所以前期可能bug會后續發現繼續修復而不是修改文章.

webpack4從零開始構建(一)
webpack4+React16項目構建(二)
webpack4功能配置劃分細化(三)
webpack4引入Ant Design和Typescript(四)
webpack4 代碼去重,簡化信息和構建優化(五)

2024/04/16上傳,代碼同步到引入antd webpack4_demo_antd

抽取配置參數

同級目錄新建文件env.js文件,我們將一些環境變量和配置變量獨立開來,盡量不耦合進webpack文件里.如下所示

const path = require('path');

const isDev = process.env.NODE_ENV !== "DEV",
  isProd = process.env.NODE_ENV !== "PROD",
  isServer = process.env.NODE_ENV !== "SERVER",

  entry = "./src/index.tsx",
  outputName = "[name].bundle.js",
  outputPath = path.resolve(__dirname, "../dist"),
  publicPath = "",

  title = "test";

module.exports = {
  isDev,
  isProd,
  isServer,
  entry,
  outputName,
  outputPath,
  publicPath,
  title
};

webpack.common.js

相關變量替換如下:

...省略
const { isProd, entry,
    outputName,
    outputPath,
    publicPath, title } = require('./env');

module.exports = {
  // 入口
  entry,
  // 輸出
  output: {
    // 打包文件名
    filename: outputName,
    // 輸出路徑
    path: outputPath,
    // 資源請求路徑
    publicPath
  },
  module: {
    rules
  },
  plugins: [
    // 清除文件
    new CleanWebpackPlugin(),
    // 提取樣式文件
    new MiniCssExtractPlugin({
      // Options similar to the same options in webpackOptions.output
      // both options are optional
      filename:
        !isProd
          ? "[name].css"
          : "style/[name].[contenthash].css",
      chunkFilename:
        !isProd
          ? "[id].css"
          : "style/[id].[contenthash].css"
    }),
    new HtmlWebpackPlugin({
      // title
      title,
      // 模板
      template: "index.html"
    })
  ],
  ...省略
};

進度條展示

yarn add progress-bar-webpack-plugin
-------------------------------------------
new VueLoaderPlugin()

目測沒啥用處,求個視覺效果吧

定義環境變量

new webpack.DefinePlugin({
  'process.env.project': 'demo'
}),

plugins部分最終代碼如下:

  plugins: [
    // 清除文件
    new CleanWebpackPlugin(),
    // 進度條展示
    new ProgressBarPlugin(),
    // 該插件幫助我們安心地使用環境變量
    new webpack.DefinePlugin({
      'process.env.project': 'demo'
    }),
    // 提取樣式文件
    new MiniCssExtractPlugin({
      // Options similar to the same options in webpackOptions.output
      // both options are optional
      filename:
        !isProd
          ? "[name].css"
          : "style/[name].[contenthash].css",
      chunkFilename:
        !isProd
          ? "[id].css"
          : "style/[id].[contenthash].css"
    }),
    new HtmlWebpackPlugin({
      // title
      title,
      // 模板
      template: "index.html"
    })
  ],

輸出信息

我們可以自定義webpack打包的輸出信息,因為比較多字段,所以同級目錄新增stats.js文件,具體似乎出看自己需求自由改動吧

module.exports = {
    // 未定義選項時,stats 選項的備用值(fallback value)(優先級高于 webpack 本地默認值)
    all: undefined,

    // 添加資源信息
    assets: true,

    // 對資源按指定的字段進行排序
    // 你可以使用 `!field` 來反轉排序。愛掏網 - it200.com
    // Some possible values: 'id' (default), 'name', 'size', 'chunks', 'failed', 'issuer'
    // For a complete list of fields see the bottom of the page
    assetsSort: 'field',

    // 添加構建日期和構建時間信息
    builtAt: true,

    // 添加緩存(但未構建)模塊的信息
    cached: true,

    // 顯示緩存的資源(將其設置為 `false` 則僅顯示輸出的文件)
    cachedAssets: true,

    // 添加 children 信息
    children: true,

    // 添加 chunk 信息(設置為 `false` 能允許較少的冗長輸出)
    chunks: false,

    // 添加 namedChunkGroups 信息
    chunkGroups: false,

    // 將構建模塊信息添加到 chunk 信息
    chunkModules: false,

    // 添加 chunk 和 chunk merge 來源的信息
    chunkOrigins: false,

    // 按指定的字段,對 chunk 進行排序
    // 你可以使用 `!field` 來反轉排序。愛掏網 - it200.com默認是按照 `id` 排序。愛掏網 - it200.com
    // Some other possible values: 'name', 'size', 'chunks', 'failed', 'issuer'
    // For a complete list of fields see the bottom of the page
    chunksSort: 'field',

    // `webpack --colors` 等同于
    colors: true,

    // 顯示每個模塊到入口起點的距離(distance)
    depth: false,

    // 通過對應的 bundle 顯示入口起點
    entrypoints: false,

    // 添加 --env information
    env: false,

    // 添加錯誤信息
    errors: true,

    // 添加錯誤的詳細信息(就像解析日志一樣)
    errorDetails: true,

    /* // 將資源顯示在 stats 中的情況排除
    // 這可以通過 String, RegExp, 獲取 assetName 的函數來實現
    // 并返回一個布爾值或如下所述的數組。愛掏網 - it200.com
    excludeAssets: "filter" | /filter/ | (assetName) => true | false |
      ["filter"] | [/filter/] | [(assetName) => true | false],

    // 將模塊顯示在 stats 中的情況排除
    // 這可以通過 String, RegExp, 獲取 moduleSource 的函數來實現
    // 并返回一個布爾值或如下所述的數組。愛掏網 - it200.com
    excludeModules: "filter" | /filter/ | (moduleSource) => true | false |
      ["filter"] | [/filter/] | [(moduleSource) => true | false],

    // 查看 excludeModules
    exclude: "filter" | /filter/ | (moduleSource) => true | false |
      ["filter"] | [/filter/] | [(moduleSource) => true | false], */

    // 添加 compilation 的哈希值
    hash: true,

    // 設置要顯示的模塊的最大數量
    // maxModules: 15,

    // 添加構建模塊信息
    modules: true,

    // 按指定的字段,對模塊進行排序
    // 你可以使用 `!field` 來反轉排序。愛掏網 - it200.com默認是按照 `id` 排序。愛掏網 - it200.com
    // Some other possible values: 'name', 'size', 'chunks', 'failed', 'issuer'
    // For a complete list of fields see the bottom of the page
    modulesSort: 'field',

    // 顯示警告/錯誤的依賴和來源(從 webpack 2.5.0 開始)
    moduleTrace: true,

    // 當文件大小超過 `performance.maxAssetSize` 時顯示性能提示
    performance: true,

    // 顯示模塊的導出
    providedExports: false,

    // 添加 public path 的信息
    publicPath: false,

    // 添加模塊被引入的原因
    reasons: false,

    // 添加模塊的源碼
    source: false,

    // 添加時間信息
    timings: true,

    // 顯示哪個模塊導出被用到
    usedExports: false,

    // 添加 webpack 版本信息
    version: false,

    // 添加警告
    warnings: true,

    // 過濾警告顯示(從 webpack 2.4.0 開始),
    // 可以是 String, Regexp, 一個獲取 warning 的函數
    // 并返回一個布爾值或上述組合的數組。愛掏網 - it200.com第一個匹配到的為勝(First match wins.)。愛掏網 - it200.com
    // warningsFilter: "filter" | /filter/ | ["filter", /filter/] | (warning) => true| false
  }

禁止體積警告

performance: {
    hints: false // 取消靜態文件超過250kb的警告
},

設置后不影響打包,只是不會提示

完整代碼

const HtmlWebpackPlugin = require("html-webpack-plugin"),
  CleanWebpackPlugin = require("clean-webpack-plugin"),
  MiniCssExtractPlugin = require("mini-css-extract-plugin"),
  ProgressBarPlugin = require('progress-bar-webpack-plugin'),
  webpack = require('webpack'),
  alias = require("./alias"),
  rules = require("./rules"),
  stats = require("./stats"),
  {
    isProd, entry,
    outputName,
    outputPath,
    publicPath, title
  } = require('./env');

module.exports = {
  // 入口
  entry,
  // 輸出
  output: {
    // 打包文件名
    filename: outputName,
    // 輸出路徑
    path: outputPath,
    // 資源請求路徑
    publicPath
  },
  module: {
    rules
  },
  stats,
  performance: {
    hints: false // 取消靜態文件超過250kbkb的警告
  },
  plugins: [
    // 清除文件
    new CleanWebpackPlugin(),
    // 進度條展示
    new ProgressBarPlugin(),
    // 該插件幫助我們安心地使用環境變量
    new webpack.DefinePlugin({
      'process.env.project': 'demo'
    }),
    // 提取樣式文件
    new MiniCssExtractPlugin({
      // Options similar to the same options in webpackOptions.output
      // both options are optional
      filename:
        !isProd
          ? "[name].css"
          : "style/[name].[contenthash].css",
      chunkFilename:
        !isProd
          ? "[id].css"
          : "style/[id].[contenthash].css"
    }),
    new HtmlWebpackPlugin({
      // title
      title,
      // 模板
      template: "index.html"
    })
  ],
  resolve: {
    // Add '.ts' and '.tsx' as resolvable extensions.
    extensions: [".ts", ".tsx", ".js", ".json"],
    // 創建 import 或 require 的別名,來確保模塊引入變得更簡單
    alias
  }
};

rules.js

原本代碼充斥很多重復代碼,將他們提取出來

const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const tsImportPluginFactory = require("ts-import-plugin");
const {
  isProd, isServer, entry,
  outputName,
  outputPath,
  publicPath, title
} = require('./env')

const cssMiniLoader = !isServer
  ? {
    loader: MiniCssExtractPlugin.loader,
    options: {
      // you can specify a publicPath here
      // by default it use publicPath in webpackOptions.output
      publicPath: process.env.NODE_ENV === "DEV" ? "./" : "../"
    }
  }
  : "style-loader"; // 使用

因為現在已經有awesome-typescript-loader處理,所以我們可以將js規則去掉.同時默認會禁止babel,如果需要的話可以配置babelOptions

webpack.server.js

我們稍微再細致一下配置,修改如下

const path = require('path'),
  webpack = require('webpack'),
  merge = require('webpack-merge'),
  common = require('./webpack.common.js'),
  BundleAnalyzerPlugin = require('webpack-bundle-analyzer')
    .BundleAnalyzerPlugin;

module.exports = merge(common, {
  mode: "development",
  // 原始源代碼(僅限行)
  devtool: "cheap-module-eval-source-map",
  devServer: {
    clientLogLevel: 'warning', // none,error,warning
    // 打開模式, Iframe mode和Inline mode最后達到的效果都是一樣的,都是監聽文件的變化,然后再將編譯后的文件推送到前端,完成頁面的reload的
    inline: true,
    progress: true,
    // 指定了服務器資源的根目錄
    contentBase: path.join(__dirname, '../'),
    // 是否開啟gzip壓縮
    compress: false,
    port: 9000,
    // 是否開啟熱替換功能
    // hot: true,
    host: 'localhost',
    // 是否自動打開頁面,可以傳入指定瀏覽器名字打開
    open: false,
    // 是否開啟部分熱替換功能
    hotOnly: true,
    proxy: {

    },
    // Shows a full-screen overlay in the browser when there are compiler errors or warnings. Disabled by default. If you want to show only compiler errors:
    overlay: { warnings: false, errors: true },
    /* 惰性模式 將不監視文件改動,不想使用自動刷新功能時可設置為true */
    lazy: false,
    /* 靜默模式,減少不必要的信息輸出 necessary for FriendlyErrorsPlugin */
    quiet: false,
    watchOptions: {
      // Turn on polling by passing true, or specifying a poll interval in milliseconds:
      poll: false
    },
    // 同stats
    stats: {
      builtAt: true,
      colors: true,
      modules: false,
      children: false,
      chunks: false,
      chunkModules: false,
      // 添加時間信息
      timings: true
    }
  },
  plugins: [
    // 熱替換模塊
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update.
    new webpack.NoEmitOnErrorsPlugin() //在編譯出現錯誤時,使用 NoEmitOnErrorsPlugin 來跳過輸出階段。愛掏網 - it200.com這樣可以確保輸出資源不會包含錯誤。愛掏網 - it200.com對于所有資源,統計資料(stat)的 emitted 標識都是 false
    // 性能可視化
    // new BundleAnalyzerPlugin()
  ]
});

生產構建優化

當前配置代碼如下

const merge = require("webpack-merge"),
  common = require("./webpack.common.js"),
  OptimizeCssAssetsPlugin = require("optimize-css-assets-webpack-plugin"),
  ParallelUglifyPlugin = require('webpack-parallel-uglify-plugin');

module.exports = merge(common, {
  mode: "production",
  // 原始源代碼
  devtool: "cheap-module-eval-source-map",
  plugins: [new OptimizeCssAssetsPlugin()]
});

可以看出構建文件和耗費時間

刪除映射

devtool: "none",

提供公共庫

簡單將node_modules和業務代碼分開

  optimization: {
    // Setting optimization.runtimeChunk to true or "multiple" adds an additional chunk to each entrypoint containing only the runtime. This setting is an alias for:
    runtimeChunk: {
      name: 'manifest'
    },
    splitChunks: {
      minSize: 0,
      cacheGroups: {
        vendor: {
          // 優先級高于其他就不會被打包進其他chunk,如果想匹配自己定義的拆分規則,則priority需要設置為正數,優先匹配默認拆分規則就設置為負數。愛掏網 - it200.com
          priority: 10,
          name: 'vendor',
          test: /[\\/]node_modules[\\/]/,
          chunks: 'all'
        }
      }
    }
  },

結果如下

引入webpack-parallel-uglify-plugin

這插件能為多入口文件啟用多線程構建,提高打包速度,這里demo比較簡單暫時用不到,但是我們可以利用他做一些特殊處理

    minimizer: [
      // This plugin serves to help projects with many entry points speed up their builds. The UglifyJS plugin provided with webpack runs sequentially on each of the output files. This plugin runs uglify in parallel with one thread for each of your available cpus. This can lead to significantly reduced build times as minification is very CPU intensive.
      new ParallelUglifyPlugin({ 
        // Optional absolute path to use as a cache. If not provided, caching will not be used.
        cacheDir: '.cache/',
        // 傳遞給 UglifyJS的參數如下:
        uglifyJS: {
          output: {
            /*
             是否輸出可讀性較強的代碼,即會保留空格和制表符,默認為輸出,為了達到更好的壓縮效果,
             可以設置為false
            */
            beautify: false,
            /*
           是否保留代碼中的注釋,默認為保留,為了達到更好的壓縮效果,可以設置為false
          */
            comments: false
          },
          compress: {
            /*
             是否在UglifyJS刪除沒有用到的代碼時輸出警告信息,默認為輸出,可以設置為false關閉這些作用
             不大的警告
            */
            warnings: false,

            /*
           是否刪除代碼中所有的console語句,默認為不刪除,開啟后,會刪除所有的console語句
          */
            drop_console: true,

            /*
           是否內嵌雖然已經定義了,但是只用到一次的變量,比如將 var x = 1; y = x, 轉換成 y = 5, 默認為不
           轉換,為了達到更好的壓縮效果,可以設置為false
          */
            collapse_vars: true,

            /*
           是否提取出現了多次但是沒有定義成變量去引用的靜態值,比如將 x = 'xxx'; y = 'xxx'  轉換成
           var a = 'xxxx'; x = a; y = a; 默認為不轉換,為了達到更好的壓縮效果,可以設置為false
          */
            reduce_vars: true
          }
        }
      })
    ]

最終代碼

const merge = require("webpack-merge"),
  common = require("./webpack.common.js"),
  OptimizeCssAssetsPlugin = require("optimize-css-assets-webpack-plugin"),
  ParallelUglifyPlugin = require('webpack-parallel-uglify-plugin');

module.exports = merge(common, {
  mode: "production",
  // 原始源代碼
  devtool: "none",
  optimization: {
    // Setting optimization.runtimeChunk to true or "multiple" adds an additional chunk to each entrypoint containing only the runtime. This setting is an alias for:
    runtimeChunk: {
      name: 'manifest'
    },
    splitChunks: {
      minSize: 0,
      cacheGroups: {
        vendor: {
          // 優先級高于其他就不會被打包進其他chunk,如果想匹配自己定義的拆分規則,則priority需要設置為正數,優先匹配默認拆分規則就設置為負數。愛掏網 - it200.com
          priority: 10,
          name: 'vendor',
          test: /[\\/]node_modules[\\/]/,
          chunks: 'all'
        }
      }
    },
    minimizer: [
      // This plugin serves to help projects with many entry points speed up their builds. The UglifyJS plugin provided with webpack runs sequentially on each of the output files. This plugin runs uglify in parallel with one thread for each of your available cpus. This can lead to significantly reduced build times as minification is very CPU intensive.
      new ParallelUglifyPlugin({ 
        // Optional absolute path to use as a cache. If not provided, caching will not be used.
        cacheDir: '.cache/',
        // 傳遞給 UglifyJS的參數如下:
        uglifyJS: {
          output: {
            /*
             是否輸出可讀性較強的代碼,即會保留空格和制表符,默認為輸出,為了達到更好的壓縮效果,
             可以設置為false
            */
            beautify: false,
            /*
           是否保留代碼中的注釋,默認為保留,為了達到更好的壓縮效果,可以設置為false
          */
            comments: false
          },
          compress: {
            /*
             是否在UglifyJS刪除沒有用到的代碼時輸出警告信息,默認為輸出,可以設置為false關閉這些作用
             不大的警告
            */
            warnings: false,

            /*
           是否刪除代碼中所有的console語句,默認為不刪除,開啟后,會刪除所有的console語句
          */
            drop_console: true,

            /*
           是否內嵌雖然已經定義了,但是只用到一次的變量,比如將 var x = 1; y = x, 轉換成 y = 5, 默認為不
           轉換,為了達到更好的壓縮效果,可以設置為false
          */
            collapse_vars: true,

            /*
           是否提取出現了多次但是沒有定義成變量去引用的靜態值,比如將 x = 'xxx'; y = 'xxx'  轉換成
           var a = 'xxxx'; x = a; y = a; 默認為不轉換,為了達到更好的壓縮效果,可以設置為false
          */
            reduce_vars: true
          }
        }
      })
    ]
  },

  plugins: [new OptimizeCssAssetsPlugin()]
});

打包結果

聲明:所有內容來自互聯網搜索結果,不保證100%準確性,僅供參考。如若本站內容侵犯了原著者的合法權益,可聯系我們進行處理。
發表評論
更多 網友評論0 條評論)
暫無評論

返回頂部

主站蜘蛛池模板: 色釉釉www网址| 91精品免费国产高清在线| 特级无码毛片免费视频尤物| 在现免费看的www视频的软件| 亚洲欧美清纯校园另类| 日本三级香港三级人妇99视| 日韩系列第一页| 四虎a456tncom| 99精品无人区乱码在线观看| 欧美大片在线观看完整版| 国产女人18毛片水真多18精品| 中文字幕精品一区二区三区视频| 男男动漫全程肉无删减彩漫| 国产精品美女久久久久av超清| 久久男人资源站| 精品国产一区二区三区久久狼| 国内精品久久人妻无码不卡| 亚洲AV之男人的天堂| 老鸭窝毛片一区二区三区| 大又大粗又爽又黄少妇毛片| 亚洲av无码专区在线播放| 色八a级在线观看| 在线观看www日本免费网站| 亚洲av网址在线观看| 老马的春天顾晓婷5| 在线播放第一页| 久久狠狠色噜噜狠狠狠狠97| 精品久久久久久中文字幕无碍| 国产精品无码一区二区三区在| 久久国产免费观看精品3| 男人j进女人j啪啪无遮挡动态| 国产特级毛片aaaaaa毛片| 中文字幕你懂的| 毛片免费视频播放| 国产午夜无码片在线观看影院| mm1313亚洲精品无码又大又粗| 极品丝袜乱系列全集| 全彩本子里番调教仆人| 亚洲精品456| 小sao货水好多真紧h视频| 亚洲av无码专区在线观看成人|