webpack4 學習

webpack 配置學習

如下是我學習webpack過程當中遇到的問題以及記錄。
基本配置可參見官方配置javascript

mode 環境的定義

生產環境:production
開發環境:development
不定義環境:nonecss

entry 入口文件

  • 單入口:"path/to/entry.js",等價於{main:"path/to/entry.js"}。配合路由插件實現多頁面。
  • 多入口:{a:"path/to/entryA.js",b:"path/to/entryB.js"}

這裏的"path/to/entry.js",必須使用絕對路徑,相對路徑會打包報錯,找不到文件。能夠利用node.jspath模塊來自動生成絕對路徑。(不須要單獨安裝path庫)。代碼以下:html

const path = require("path");

config = {
  // 這裏的 __dirname 是node.js的全局變量,指的是當前js文件所在絕對路徑
  entry: path.resolve(__dirname, "path/to/entry.js")
};
多入口若是這樣寫 ["path/to/entryA.js","path/to/entryB.js"],會致使打包的 js 只有一個 main.js,邏輯全都掛載在頁面 A,頁面 B是空白的。因此不建議這樣寫。

output 打包輸出配置

經常使用的幾個配置選項以下:java

  • path:指的是打包文件輸出的根目錄,必須使用絕對路徑。
  • filename:打包後的js文件名。例如"js/[name].[hash:8].bundle.js",這裏的[name]指的是入口entry中定義的main a b
  • publicPath:是生成的js,css,images等靜態資源的引用路徑的基本路徑。例如/assets/,那麼在打包生成的html文件中引入的js,css,images等靜態資源的路徑的前面會所有自帶/assets/。還可使用例如https://cdn.example.com/這樣的 cdn 配置,這樣能夠更好的處理生產環境使用 cdn 靜態資源的狀況。通常不作這項配置也可。

module 處理靜態資源的規則

詳細可參見官方配置node

  • 處理圖片文件webpack

    須要安裝模塊file-loader,url-loadergit

    具體配置以及說明可參見以下代碼:github

    {
      test: /\.(png|svg|jpg|gif|jpeg|tif)$/,
      use: [
        // {
        // webpack經過file-loader處理資源文件,它會將rules規則命中的資源文件按照配置的信息(路徑,名稱等)輸出到指定目錄,
        // 並返回其資源定位地址(輸出路徑,用於生產環境的publicPath路徑),默認的輸出名是以原文件內容計算的MD5 Hash命名的
        //   loader: "file-loader",
        //   options: {
        //       outputPath: "images/"
        //   }
        // },
        {
          // 構建工具經過url-loader來優化項目中對於資源的引用路徑,並設定大小限制,當資源的體積小於limit時將其直接進行Base64轉換後嵌入引用文件,體積大於limit時可經過fallback參數指定的loader進行處理。
          // 打包後能夠看到小於8k的資源被直接內嵌進了CSS文件而沒有生成獨立的資源文件
          loader: "url-loader",
          options: {
            limit: 8129, //小於limit限制的圖片將轉爲base64嵌入引用位置
            fallback: "file-loader", //大於limit限制的將轉交給指定的loader處理,開啓這裏後就無需再單獨配置file-loader options會直接傳給fallback指定的loader
            name: "[name].[ext]",
            outputPath: "images", //這裏是打包後圖片所在的位置
            //這裏的publicPath做用和output配置中的相同,會覆蓋output中的配置項。
            //爲了防止css中引入圖片路徑的問題,能夠在這裏判斷若是是開發環境熱更新啓動模式,改爲用根目錄的路徑 /images
            publicPath: "./images"
          }
        }
      ]
    }
  • 處理字體文件web

    和圖片文件的處理同樣,須要安裝file-loader模塊。npm

    具體配置可參見以下代碼:

    {
      test: /\.(woff|woff2|eot|ttf|otf)$/,
      use: [
        {
          loader: "file-loader",
          options: {
            outputPath: "css/fonts",
            publicPath: "fonts",
            name: "[name].[hash:8].[ext]"
          }
        }
      ]
    }
  • 處理css樣式文件

    css不分離的話,就是樣式<style></style>都在html文件的的head標籤裏面。須要安裝style-loader模塊。

    若是css分離,則能夠異步同時加載html文件和css文件,能夠有效提升加載速度。須要安裝mini-css-extract-plugin模塊(extract-text-webpack-plugin模塊不支持webpack4以上的版本)。

    另外還須要安裝css-loader模塊。

    postcss-loader模塊的做用後面會講到。

    具體配置以及說明可參見以下代碼:

    const miniCssExtractPlugin = require("mini-css-extract-plugin");
    
    {
      test: /\.css$/,
      include: [path.resolve(__dirname, "src")], // 限制打包範圍,提升打包速度
      exclude: /node_modules/, // 排除node_modules文件夾
      use: [
        // {    // 當配置MinCssExtractPlugin.loader後,此項就無需配置,緣由看各自做用
        //     loader: "style-loader"  // 將處理結束的css代碼存儲在js中,運行時嵌入`<style>`後掛載到html頁面上
        // },
        {
          // 將處理後的CSS代碼提取爲獨立的CSS文件,能夠只在生產環境中配置,但我喜歡保持開發環境與生產環境儘可能一致
          loader: miniCssExtractPlugin.loader
        },
        {
          // CSS加載器,使webpack能夠識別css文件
          loader: "css-loader"
        },
        {
          //承載autoprefixer功能,爲css添加前綴
          loader: "postcss-loader"
        }
      ]
    }
  • 處理scss樣式文件

    須要安裝的模塊同上面css同樣。另外還須要安裝node-sasssass-loader模塊。

    postcss-loader模塊這裏須要安裝postcss-scss插件來識別處理scss文件。

    具體配置以及說明可參見以下代碼:

    {
      test: /\.scss$/,
      include: [path.resolve(__dirname, "src")], // 限制打包範圍,提升打包速度
      exclude: /node_modules/, // 排除node_modules文件夾
      use: [
        // {    // 當配置MinCssExtractPlugin.loader後,此項就無需配置,緣由看各自做用
        //     loader: "style-loader"  // 將處理結束的css代碼存儲在js中,運行時嵌入`<style>`後掛載到html頁面上
        // },
        {
          // 將處理後的CSS代碼提取爲獨立的CSS文件,能夠只在生產環境中配置,但我喜歡保持開發環境與生產環境儘可能一致
          loader: miniCssExtractPlugin.loader
        },
        {
          // CSS加載器,使webpack能夠識別css文件
          loader: "css-loader"
        },
        {
          //承載autoprefixer功能,爲css添加前綴
          loader: "postcss-loader",
          options: {
            parser: "postcss-scss"
          }
        },
        {
          // 編譯sass,webpack默認使用node-sass進行編譯,因此須要同時安裝 sass-loader 和 node-sass
          loader: "sass-loader"
        }
      ]
    }
  • 處理less樣式文件

    須要安裝的模塊同上面css同樣。另外還須要安裝lessless-loader模塊。

    postcss-loader模塊這裏須要安裝postcss-less插件來識別處理less文件。

    具體配置以及說明可參見以下代碼:

    {
      test: /\.less$/,
      include: [path.resolve(__dirname, "src")], // 限制打包範圍,提升打包速度
      exclude: /node_modules/, // 排除node_modules文件夾
      use: [
        // {    // 當配置MinCssExtractPlugin.loader後,此項就無需配置,緣由看各自做用
        //     loader: "style-loader"  // 將處理結束的css代碼存儲在js中,運行時嵌入`<style>`後掛載到html頁面上
        // },
        {
          // 將處理後的CSS代碼提取爲獨立的CSS文件,能夠只在生產環境中配置,但我喜歡保持開發環境與生產環境儘可能一致
          loader: miniCssExtractPlugin.loader
        },
        {
          // CSS加載器,使webpack能夠識別css文件
          loader: "css-loader",
          options: {
            // 不處理引入圖片的路徑問題
            url: false,
            importLoaders: 1
          }
        },
        {
          //承載autoprefixer功能,爲css添加前綴 瀏覽器css前綴
          loader: "postcss-loader",
          options: {
            parser: "postcss-less"
          }
        },
        {
          // 編譯less,webpack默認使用less進行編譯,因此須要同時安裝 less-loader 和 less
          loader: "less-loader"
        }
      ]
    }
  • 處理csv|tsv文件

    須要安裝csv-loader模塊來識別這些文件。

    {
      test: /\.(csv|tsv)$/,
      use: ["csv-loader"]
    }
  • 處理xml文件

    須要安裝xml-loader模塊來識別這些文件。

    {
      test: /\.xml$/,
      use: ["xml-loader"]
    }
  • postcss-loader模塊

    PostCSS 是一個容許使用 JS 插件轉換樣式的工具。 這些插件能夠檢查(lint)你的 CSS,支持 CSS Variables 和 Mixins, 編譯還沒有被瀏覽器普遍支持的先進的 CSS 語法,內聯圖片,以及其它不少優秀的功能。

    postcss有許多插件,插件以及配置信息,具體可參見官方說明

    配置文件默認是postcss.config.js

    處理.sass須要安裝postcss-sass轉換器。處理.scss文件須要安裝postcss-scss轉換器。處理.less文件須要安裝postcss-less轉換器。
    在這裏我用了兩個插件autoprefixerprecss

    autoprefixer自動添加各個瀏覽器css前綴,須要package.json文件中配置支持的瀏覽器列表browserslist,才能正確加上所配置瀏覽器的前綴。具體可查看官方說明

    precss是讓你能夠在css文件中使用像scss文件中的變量以及鏈接符。具體可查看官方說明

    或許cssnano插件一些人會用,這個是壓縮css的。我這裏壓縮css用的另外的插件,沒有用postcss,後面會講到。

plugins 插件配置

  • html-webpack-plugin

    這是生成html文件的插件,會把打包生成的css文件以及js文件自動插入到生成的html文件中。具體可參見官方說明

    能夠動態生成,適用於多入口。單入口只寫一個就能夠了。具體配置以及說明可參見以下代碼:

    const HtmlWebpackPlugin = require("html-webpack-plugin");
    
    new HtmlWebpackPlugin({
      // 頁面title 若是使用自定義的摸板,那麼摸板title標籤內容爲<%= htmlWebpackPlugin.options.title %>纔可在生成的html文件中正確替換。
      title: "index",
      // 生成的html的文件名以及位置 可添加上相對於打包輸出的路徑,好比"views/index.html"
      filename: "index.html",
      // 所使用的自定義摸板 不寫表示使用官方默認的摸板
      // 自定義摸板能夠添加一些cdn公共庫,添加公共庫還能夠用下一小節中的方法
      // template: "src/index.html",
      // 須要插入的js模塊
      // main表示入口主文件
      // common表示提取的公共模塊,在optimization.splitChunks中定義的
      // vendors表示提取的第三方模塊,即npm安裝的模塊,也是在optimization.splitChunks中定義的
      // manifest運行時的模塊,在optimization.runtimeChunk中定義的。
      chunks: ["main", "common", "vendors", "manifest"],
      // 頁面圖標
      favicon: "src/images/備案圖標.png", // 配置每一個html頁面的favicon
      // 壓縮選項配置
      minify: {
        // 壓縮HTML文件
        removeComments: true, // 移除HTML中的註釋
        collapseWhitespace: true // 刪除空白符與換行符
        // css js已經壓縮了,這裏再也不配置壓縮
        //是否壓縮html裏的js 我這裏使用的optimization.minimizer中配置的插件壓縮
        // minifyJS: true,
        // 壓縮html裏的css 我這裏使用的optimization.minimizer中配置的插件壓縮
        // minifyCSS: true // 壓縮內聯css
      },
      // 請求js css資源時,附帶哈希值 這對緩存清除(cache busting)十分有用。
      hash: true
    })
  • 第三方庫的公共引入 暴露全局 不用單獨 import

    這裏是引入公共的第三方模塊,並暴露全局變量。使用時不用單獨引入,能夠直接使用暴露的全局變量。

    也可使用上一小節中提到的html摸板中插入cdn公共庫連接的方法,這樣能夠減小本身服務器的壓力。

    具體配置以及說明可參見以下代碼:

    const webpack = require("webpack");
    
    // _是暴露的全局變量名稱 "lodash"是引入的公共第三方庫
    new webpack.ProvidePlugin({
      _: "lodash"
    })
  • mini-css-extract-plugin

    這個插件在處理css,scss,less文件的時候也有說明,這裏主要是對打包輸出css文件的配置。具體可參見官方說明

    具體配置以及說明可參見以下代碼:

    new miniCssExtractPlugin({
      // 打包後的css文件輸出路徑以及名稱
      filename: "css/[name].[hash:8].css"
    })
  • clean-webpack-plugin

    這個插件的做用是每次打包,清理過時文件。具體可參見官方說明

    具體配置以及說明可參見以下代碼:

    const { CleanWebpackPlugin } = require("clean-webpack-plugin");
    
    // plugins中簡單的插入這一句便可
    new CleanWebpackPlugin()
  • purifycss-webpack

    這個插件的做用是打包過程當中消除無用多餘的css樣式。須要配合glob使用。

    具體配置以及說明可參見以下代碼:

    const glob = require("glob");
    const PruifyCSSPlugin = require("purifycss-webpack");
    
    new PruifyCSSPlugin({
      // src下全部的html
      // paths: glob.sync(path.join(__dirname, "src/*.html"))
      // src下全部的js
      paths: glob.sync(path.join(__dirname, "./src/**/*.js"))
    })

optimization

優化打包的配置。具體可參見官方說明

  • splitChunks

    找到 chunk 中共享的模塊,取出來生成單獨的 chunk。

    具體配置以及說明可參見以下代碼:

    splitChunks: {
      chunks: "all", // async表示抽取異步模塊,all表示對全部模塊生效,initial表示對同步模塊生效
      cacheGroups: {
        vendors: {
          // 抽離第三方插件
          test: /[\\/]node_modules[\\/]/, // 指定是node_modules下的第三方包
          // 打包後的模塊文件名稱
          name: "vendors",
          priority: -10 // 抽取優先級
        },
        commons: {
          // 抽離自定義工具庫
          name: "common",
          priority: -20, // 抽取優先級
          minChunks: 2, // 表示將引用模塊如不一樣文件引用了多少次,才能分離生成新chunk
          minSize: 0 // 將引用模塊分離成新代碼文件的最小體積
        }
      }
    }
  • minimizer

    代碼壓縮 僅當mode='production'時生效。

    具體配置以及說明可參見以下代碼:

    const OptimizeCssAssetsWebpackPlugin = require("optimize-css-assets-webpack-plugin");
    const TerserPlugin = require("terser-webpack-plugin");
    
    minimizer: [
      // 對生成的CSS文件進行壓縮
      new OptimizeCssAssetsWebpackPlugin({
        cssProcessorPluginOptions: {
          // options 去掉註釋
          preset: ["default", { discardComments: { removeAll: true } }]
        }
      }),
      // 壓縮js
      new TerserPlugin({
        minify: (file, sourceMap) => {
          // https://github.com/mishoo/UglifyJS2#minify-options
          const uglifyJsOptions = {
            /* your `uglify-js` package options */
            output: {
              // 去掉註釋
              comments: false
            },
            compress: {
              // 去掉控制檯打印
              drop_debugger: true,
              drop_console: true
            }
          };
    
          if (sourceMap) {
            uglifyJsOptions.sourceMap = {
              content: sourceMap
            };
          }
    
          return require("uglify-js").minify(file, uglifyJsOptions);
        }
      })
    ]
  • runtimeChunk

    webpack 運行時代碼建立單獨的 chunk

    詳細說明可參見官方說明

    runtimeChunk: {
      name: "manifest"
    }

代碼熱更新 瀏覽器自動刷新

開發環境的配置,可參見webpack開發環境

自動編譯官方列舉了三種方式,這裏我使用的是webpack-dev-server模塊。詳細配置項可參見官方說明

具體配置以及說明可參見以下代碼webpack.config.dev.js

const chalk = require("chalk"); // 改變命令行中輸出日誌顏色插件
const ip = require("ip").address();

// source-map控制檯追尋到源代碼的文件。
devtool: "inline-source-map",
devServer: {
  // 運行時的目錄
  contentBase: path.resolve(__dirname, "dev"),
  // 當使用 HTML5 History API 時,任意的 404 響應均可能須要被替代爲 index.html。
  historyApiFallback: true,
  // 指定使用一個 host。默認是 localhost。
  host: ip,
  // 控制檯顯示啓動過程進度
  progress: true,
  // 當出現編譯器錯誤或警告時,在瀏覽器中顯示全屏覆蓋。默認狀況下禁用。
  overlay: true,
  // 自動打開瀏覽器
  open: true,
  // 啓用 webpack 的模塊熱替換特性
  hot: true,
  after() {
    console.log(chalk.cyan(`http://${ip}:${this.port} 已成功打開`));
  }
}
// plugins配置項中添加 new webpack.HotModuleReplacementPlugin() ,用於模塊的熱更新。

devServer中的配置項通常也能夠在npx命令中配置使用,這樣可使用一個config文件,來條件編譯便可。

package.json中的npx命令

示例:

"scripts": {
  "test": "echo \"Error: no test specified\" && exit 1",
  "watch": "webpack --watch",
  "start": "webpack-dev-server --config=webpack.config.dev.js",
  "dev": "cross-env NODE_ENV=development webpack --progress --colors --devtool cheap-module-source-map",
  "build": "webpack --progress --colors"
}
  • cross-env模塊

    可在命令中定義環境變量。cross-env NODE_ENV=development,在這裏定義了環境變量,就能夠在配置文件webpack.config.js中得到並使用這個變量,以處理條件編譯。

    得到環境變量:const env = process.env.NODE_ENV

最後可參見個人一個小demo:https://gitee.com/wtto00/webpack-demo

相關文章
相關標籤/搜索