Webpack實戰(五):輕鬆讀懂Webpack如何分離樣式文件

在上一篇文章中我給你們分享了預處理器(loader),裏面講到了style-loader 和css-loader,有關樣式引入的問題,可是上面的樣式文件只是引入到style標籤裏面,並非我想要的樣式文件獨立分離。javascript

若是想了解有關css-loader和style-loader能夠參考如下地址:css

Webpack實戰(四):教教你如何輕鬆搞定-預處理器(loader)

經過js引入樣式文件只是把樣式添加到style標籤內,而不是引入一個獨立的css文件,通常來講,在生產環境下,咱們但願樣式存在於CSS文件中而不是style標籤中,由於文件更有利於客戶端進行緩存。java

Webpack社區有專門的插件:extract-text-webpack-plugin(適用於Webpack 4以前版本)和mini-css-extract-plugin(適用於Webpack 4及以上版本),它們就是專門用於提取樣式到CSS文件的。node

  1. extract-text-webpack-plugin extract-text-webpack-plugin安裝命令代碼以下:
# for webpack 3 
npm install --save-dev extract-text-webpack-plugin
# for webpack 2 
npm install --save-dev extract-text-webpack-plugin@2.1.2
# for webpack 1 
npm install --save-dev extract-text-webpack-plugin@1.0.1
複製代碼

因爲webpack版本不同,extract-text-webpack-plugin安裝的出來版本的也不同。webpack

配置代碼以下:web

const ExtractTextPlugin = require("extract-text-webpack-plugin");
 const path = require('path')
module.exports = {
  context: path.join(__dirname, './src'),
  entry: {
    index: './index.js'
  },
  output: {
    path: path.join(__dirname, 'dist'),
    filename: 'index.js'
  },
  mode: 'development',
  module: {
    rules: [
      {
        test: /\.css$/i,
       use: ExtractTextPlugin.extract({
          fallback: "style-loader",
          use: "css-loader"
        }),
        exclude: /node_modules/
      },
      {
        test: /\.js$/,
        exclude: /(node_modules|bower_components)/,
        use: {
          loader: 'babel-loader',
          options: {
            cacheDirectory: true,
            presets: [
              [
                'env', {
                  modules: false
                }
              ]
            ]
          }
        }
      }
    ],
  },
  plugins: [
    new ExtractTextPlugin("styles.css") //提取後css文件名稱
  ]
}
複製代碼

在module.rules中咱們設置了處理CSS文件和js文件的規則,其中css配置的use字段並無直接傳入loader,而是使用了插件的extract方法包了一層。內部的fallback屬性用於指定當插件沒法提取樣式時所採用的loader,use(extract方法裏面的)用於指定在提取樣式以前採用哪些loader來預先進行處理。除此以外,還要在Webpack的plugins配置中添加該插件,並傳入提取後的資源文件名。 因爲我電腦項目裏裝的4.0以上的webpack版本,這裏再也不作打包測試。 樣式的提取是以資源入口開始的整個chunk爲單位的。好比咱們的應用從index.js開始引入了幾百個模塊,這些模塊都引入了它們各自的樣式文件,可是最終生成的c s s文件只有一個,由於它們都來自同一個入口模塊。上面咱們講styles.css做爲文件名傳給extract-text-webpack-plugin,可是當項目有多個入口的時候就會發生重名問題。就像咱們前面動態配置的output.filename同樣。這裏咱們也將要對插件提取的css文件使用相似模版的命名方式。npm

下面是入口的index.js和about.js緩存

// index.js
import './index.css'

// about.js
import './about.css'
複製代碼

we bpack.config.js配置部分代碼以下babel

const ExtractTextPlugin = require("extract-text-webpack-plugin");
 const path = require('path')
module.exports = {
  context: path.join(__dirname, './src'),
  entry: {
    index: './index.js',
    about: './about.js'
  },
  output: {
    path: path.join(__dirname, 'dist'),
    filename: '[name].js'
  },
  mode: 'development',
  module: {
    rules: [
      {
        test: /\.css$/i,
       use: ExtractTextPlugin.extract({
          fallback: "style-loader",
          use: "css-loader"
        }),
        exclude: /node_modules/
      },
      {
        test: /\.js$/,
        exclude: /(node_modules|bower_components)/,
        use: {
          loader: 'babel-loader',
          options: {
            cacheDirectory: true,
            presets: [
              [
                'env', {
                  modules: false
                }
              ]
            ]
          }
        }
      }
    ],
  },
  plugins: [
    new ExtractTextPlugin("[name].css") //提取後css文件名稱
  ]
}
複製代碼

咱們使用[name].css來動態生成c s s文件名,name爲即entry中咱們爲每個入口分配的名字(index、about),由此能夠推出[name]指的是chunk(chunk是對一組有依賴關係的模塊的封裝)的名字。異步

  1. mini-css-extract-plugin mini-css-extract-plugin 是 extract-text-webpack-plugin的升級版本,它擁有更多的特性和更好的性能。最突出的一條就是 mini-css-extract-plugin支持按需加載css,舉個例子,a.js經過import()函數異步加載了b.js,b.js裏面加載了style.css,那麼style.css最終只能被同步加載(經過HTML的link標籤)。可是如今mini-css-extract-plugin會單獨打包出一個0.css(假設使用默認配置),這個CSS文件將由a.js經過動態插入link標籤的方式加載。 首先安裝mini-css-extract-plugin
npm install --save-dev mini-css-extract-plugin
複製代碼

下面是入口的index.js和index2.js

// index.js
import './common.css'

// index2.js
import './style.css'
複製代碼

web pack.config.js配置以下:

const path = require('path')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
module.exports = {
  context: path.join(__dirname, './src'),
  entry: {
    index: './index.js',
    index2: './index2.js'
  },
  output: {
    path: path.join(__dirname, 'dist'),
    filename: '[name].js'
  },
  mode: 'development',
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [{
          loader: MiniCssExtractPlugin.loader,
          options: {
            publicPath: '../'
          },
        }, 'css-loader'],
        exclude: /node_modules/
      },
      {
        test: /\.js$/,
        exclude: /(node_modules|bower_components)/,
        use: {
          loader: 'babel-loader',
          options: {
            cacheDirectory: true,
            presets: [
              [
                'env', {
                  modules: false
                }
              ]
            ]
          }
        }
      }
    ],
  },
  plugins: [new MiniCssExtractPlugin({
    filename: '[name].css',
    chunkFilename: '[id].css'
  })],
}
複製代碼

打包效果以下:

在這裏插入圖片描述
能夠發現最後輸出兩個c s s文件名分別爲chunk 名,index.css,index2.css

在配置上mini-css-extract-plugin與extract-text-webpack-plugin有如下幾點不一樣

  • loader規則設置的形式不一樣,而且mini-css-extract-plugin支持配置publicPath,用來指定異步CSS的加載路徑。
  • 不須要設置fallback。
  • 在plugins設置中,除了指定同步加載的CSS資源名(filename),還要指定異步加載的CSS資源名(chunkFilename)。

總結

Webpack樣式文件分離,主要用兩個插件mini-css-extract-plugin與extract-text-webpack-plugin,它們有着各自的特色,可是若是webpack版本4.0以上建議用mini-css-extract-plugin,它擁有更多的特性,特別是按需加載cs s,解決了一些性能問題。

若是想了解更多,請掃描二維碼:

在這裏插入圖片描述
相關文章
相關標籤/搜索