demo14 webpack mini-css-extract-plugin + SplitChunksPlugin 處理 css 和 scss

1.關於 mini-css-extract-plugin

雖然webpack4不支持 ExtractTextWebpackPlugin 插件,可是咱們能夠使用 mini-css-extract-plugin 來實現把 css 提取爲單獨的文件。javascript

相比 ExtractTextWebpackPlugin,mini-css-extract-plugin 有以下優勢:css

  • 異步加載
  • 不重複編譯,性能更好
  • 更容易使用
  • 只針對CSS

但目前 mini-css-extract-plugin 不支持HMR。html

詳情見 mini-css-extract-plugin 官方文檔:github.com/webpack-con…java

mini-css-extract-plugin 的做用在於可以將全部的入口 chunk (entry chunks) 中引用的 *.css,移動到獨立分離的 CSS 文件中。webpack

所以,你的樣式將再也不內嵌到 JS bundle 中,而是會放到一個單獨的 CSS 文件(好比 styles.css)當中。git

若是你的樣式文件大小較大,這會作更快提早加載,由於 CSS bundle 會跟 JS bundle 並行加載。github

使用 mini-css-extract-plugin 優勢:web

  • CSS 請求並行
  • CSS 單獨緩存

缺點在於:npm

  • 須要額外的 HTTP 請求

雖然 file-loader 也能夠把 css 單獨提取到 css 文件,可是沒法合併多個css文件segmentfault

2.關於打包方案(與 SplitChunksPlugin 結合)

  • 爲 Vendor 單獨打包(Vendor 指第三方的庫或者公共的基礎組件,由於 Vendor 的變化比較少,單獨打包利於緩存)
  • 爲 Manifest (Webpack 的 Runtime 代碼)單獨打包
  • 爲不一樣入口的公共業務代碼打包(同理,也是爲了緩存和加載速度)
  • 爲異步加載的代碼打一個公共的包

juejin.im/post/5b304f…

3.異步 css 和異步 js

注意css的同步加載仍是異步加載的引用方式:

同步加載:import './style2.css';

異步加載:import('./style2.css');

兩種的打包結果是不同的

4.自動生成 html HtmlWebpackPlugin

HtmlWebpackPlugin 簡化了 HTML 文件的建立,以便爲你的 webpack 包提供服務。這對於在文件名中包含每次會隨着編譯而發生變化哈希的 webpack bundle 尤爲有用。 你可讓插件爲你生成一個HTML文件,使用 lodash 模板提供你本身的模板,或使用你本身的 loader。

segmentfault.com/a/119000000…

5.安裝相關依賴

(注意:mini-css-extract-plugin 依賴於 webpack,所以須要在項目下安裝 webpack)

npm install -D webpack
npm install -D css-loader
npm install -D mini-css-extract-plugin
npm install -D html-webpack-plugin
複製代碼

6.目錄結構

// `--` 表明目錄, `-` 表明文件
  --demo14
    --src
      --module1(同步模塊)
        -module1.css
        -module1.js
      --module2(異步模塊)
        -module2.css
        -module2.js
      --styles
        -async-style.css
        -common.css
      -app.js
    --vendor(第三方包)
      -vendor.css
      -vendor.js
    -index.html
    s-webpack.config.js
複製代碼

src/module1/module1.css

body {
  color: black;
}

複製代碼

src/module1/module1.js

import './module1.css';
console.log('這裏是同步module1');
複製代碼

src/module2/module2.css

body {
  font-size: 100px;
}
複製代碼

src/module2/module2.js

import './module2.css';
console.log('這裏是異步module2');
複製代碼

src/styles/async-style.css

body {
  background-color: red;
}
複製代碼

src/styles/common.css

body {
  font-family: monospace, "Microsoft Yahei", "微軟雅黑", STXihei, "華文細黑";
}
複製代碼

vendor/vendor.css

/* 第三方包css */
body {
  border: 1px solid black;
}

複製代碼

vendor/vendor.js

// 這裏假設vendor爲第三方包
import './vendor.css';
console.log('這裏是第三方依賴包');
複製代碼

src/app.js

// 同步加載common.css
import './styles/common.css';

// 同步加載module1.js
import * as module1 from './module1/module1';

// 同步加載第三方包vendor.js
import * as vendor from '../vendor/vendor';

window.addEventListener('click', function () {
  // 異步加載module2.js
  import(/* webpackChunkName: 'module2'*/ './module2/module2').then(_ => {
    console.log('加載異步module2成功');
  });
  // async-style.css
  import(/* webpackChunkName: 'async-style'*/'./styles/async-style.css').then(_ => {
    console.log('加載異步async-style.css成功');
  });

});
複製代碼

7.編寫 webpack 配置文件

webpack.config.js

const path = require("path");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
  mode: 'production' || 'development' || 'production',
  entry: {
    app: "./src/app.js"
  },
  output: {
    publicPath: __dirname + "/dist/", // 打包後資源文件的引用會基於此路徑
    path: path.resolve(__dirname, "dist"), // 打包後的輸出目錄
    filename: "[id].[name].[chunkhash:8].bundle.js", // 在development模式下,id爲name
    chunkFilename: "[id].[name].[chunkhash:8].chunk.js"
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
        ]
      }
    ]
  },
  optimization: {
    runtimeChunk: "single", // webpack運行時代碼單獨提取爲一個包
    splitChunks: {
      cacheGroups: {
        async: { // 爲異步代碼打成一個公共包(在app.js修改一下代碼,從新打包,不影響此包hash)
          name: 'async',
          chunks: 'async', // 爲異步代碼打包
          minChunks: 1,
          minSize: 0
        },
        vendors: { // 因爲第三方代碼變更比較小,因此把全部第三方單獨打包,利於緩存(在app.js修改一下代碼,從新打包,不影響此包hash)
          test: /[\\/]vendor[\\/]/,
          name: 'vendor',
          chunks: 'all', // 設置爲all
          minChunks: 1,
          minSize: 0// 這裏爲了演示,設置爲0以知足打包條件
        }
      }
    }
  },
  plugins: [
    new HtmlWebpackPlugin({ // 自動生成html,而且自動導入全部依賴同步包
      filename: "index.html",
      template: "./index.html",
      minify: {
        // collapseWhitespace: true // 壓縮
      }
    }),

    new MiniCssExtractPlugin({
      filename: "[id].[name].[chunkhash:8].css",
      chunkFilename: "[id].[name].[chunkhash:8].css"
    })
  ]

}
複製代碼

8.執行打包命令

(默認你已經安裝了全局 webpack 以及 webpack-cli )

webpack
複製代碼

9.驗證打包結果

輸出結果:

0.async.512ec03b.chunk.js
0.async.512ec03b.css
1.app.4cfbacec.chunk.js
1.app.4cfbacec.css
2.runtime.0d1b9de2.bundle.js
3.vendor.c1185876.chunk.js
3.vendor.c1185876.css
index.html
複製代碼

在瀏覽器運行 dist/index.html 查看效果。

10.源碼地址

demo 代碼地址: github.com/SimpleCodeC…

倉庫代碼地址(及目錄): github.com/SimpleCodeC…

相關文章
相關標籤/搜索