webpack對樣式的處理

wind4gis發表於2019-03-03

參考: github.com/zhengweiken…

我們可以在js中引入樣式檔案

require(`myStyle.css`)
複製程式碼

這時我們便需要引入相應的webpack loader來幫助我們解析這段程式碼。

css-loader搭配style-loader

首先,我們可以引入css-loader和style-loader來處理css的解析,其中,css-loader是用來解析css檔案,style-loader是用來將css檔案嵌入到js檔案裡

var path = require(`path`)
module.exports = {
  context: path.join(__dirname, `src`)
  entry: `./`,
  module: {
    rules: [
      {
        test: /.css$/,
        include: [
          path.join(__dirname, `src`)
        ],
        use: [`style-loader`, `css-loader`]
      }
    ]
  },
  output: {
      path: path.join(__dirname, `dist`),
      filename: `[name].bundle.[hash].js`
  }
}
複製程式碼

  在上面的程式碼裡,解析順序是從右到左解析,先使用css-loader解析出css檔案之後,再使用style-loader嵌入到js程式碼裡。

  如果你使用less來寫樣式的話,則需要先用less-loader來編譯樣式檔案為css檔案,再繼續使用css-loader與style-loader。另外,loader載入器可以省略後面的-loader。所以上面的程式碼可以縮寫成

module: {
	rules: [
	  {
	    test: /.css$/,
	    include: [
	      path.join(__dirname, `src`)
	    ],
	    use: [`style`, `css`, `less`]
	  }
	]
}	
複製程式碼

  一般在測試環境裡為了快點編譯css,會用這種方式多一點,但是這樣子編譯出來的js檔案會比較大,不大適合在生產環境裡使用。

編譯成單獨的檔案

  上面的做法會把css和js打包在一起,減少實際請求的次數,但是由於編譯出來的js檔案比較大,浪費頻寬。因此,我們使用extract-text-webpack-plugin外掛,把css檔案編譯成獨立的檔案。我們就可以利用CDN把這個檔案推送到節點伺服器,或者根據視情況按需載入,進而優化客戶請求鏈路,加速頁面響應。

var path = require(`path`),
	ExtractTextPlugin = require(`extract-text-webpack-plugin`)
module.exports = {
  context: path.join(__dirname, `src`),
  entry: `./`,
  module: {
    rules: [{
      test: /.css$/,
      include: [
        path.join(__dirname, `src`)
      ],
      use: ExtractTextPlugin.extract({
        fallback: `style`,
        use: `css`
      })
    }]
  },
  output: {
      path: path.join(__dirname, `dist`),
      filename: `[name].bundle.[hash].js`
  },
  plugins: [
    new ExtractTextPlugin(`[name].css`)
  ]
}
複製程式碼

  通過上面的程式碼,我們使用extract-text-webpack-plugin外掛處理src目錄下所有的css檔案,先使用css-loader外掛解析出css程式碼,如果解析失敗,使用style-loader外掛解析,最終在dist目錄下生成對應的js檔案

相容舊瀏覽器

  以前我們寫樣式時,有些樣式不同瀏覽器需要加不同的字首,如-webkit-。現在有了構建工具,我們便不需要再去關注這些字首了,構建工具會自動幫我們加上這些字首。

對於webpack我們自然想到需要使用loader或者plugin來幫助我們做這些事情,查了下發現autoprefixer-loader已經廢棄不再維護了,推薦使用posscss

postcss是用於在js中轉換css樣式的js外掛,需要搭配其他外掛一起使用,這點和babel6一樣,本身只是個轉換器,並不提供程式碼解析功能。

這裡我們需要autoprefixer外掛來為我們的樣式新增字首。首先下載該模組。

npm install -D autoprefixer
複製程式碼

接著便可以配置webpack了

var autoprefixer = require(`autoprefixer`)
module.exports = {
  ...
  module: {
    loaders: [
      ...
      {
        {
          test: /.css$/,
          loader: ExtractTextPlugin.extract(["css", "postcss"])
        },
      }
    ]
  },
  postcss: [autoprefixer()],
  ...
}
複製程式碼

檢視一下抽取出來的樣式檔案便可以發現已經加上了字首

a {
    display: flex;
}
/*compiles to:*/
a {
  display: -webkit-box;
  display: -webkit-flex;
  display: -ms-flexbox;
  display: flex
}
複製程式碼

另外autoprefixer還可以根據目標瀏覽器版本生成不同的字首個數,例如你的應用的使用使用者如果大多數是使用比較新版本的瀏覽器,那麼便可以做如下配置。

postcss: [autoprefixer({ browsers: [`last 2 versions`] })]
這是生成的樣式便會有些不一樣,還是上面的例子

a {
    display: flex;
}
/*compiles to:*/
a {
  display: -webkit-flex;
  display: -ms-flexbox;
  display: flex;
}
複製程式碼

樣式壓縮

壓縮程式碼我們可以使用webpack的內建外掛UglifyJsPlugin來做,它既可以壓縮js程式碼也可以壓縮css程式碼。

plugins: [
  ...
  new webpack.optimize.UglifyJsPlugin({
    compress: {
      warnings: false
    }
  }),
  ...
]
複製程式碼

其實並不能說是在壓縮css程式碼,本質來說還是壓縮js程式碼,再將這塊程式碼輸出到css檔案中。

使用CommonsChunkPlugin抽取公共程式碼

首先要明確一點CommonsChunkPlugin是在有多個entry時使用的,即在有多個入口檔案時,這些入口檔案可能會有一些共同的程式碼,我們便可以將這些共同的程式碼抽取出來成獨立的檔案。明白這一點非常重要。(搞了很久才明白的一點,唉~~~~)

如果在多個entry中require了相同的css檔案,我們便可以使用CommonsChunkPlugin來將這些共同的樣式檔案抽取出來為獨立的樣式檔案。

module.exports = {
  entry: {
    "A": "./src/entry.js",
    "B": "./src/entry2.js"
  },
  ...
  plugins: [
    new webpack.optimize.CommonsChunkPlugin({
		name: "commons", filename: "commons.js"
	}),
    ...
  ]
}
複製程式碼

當然,這裡不止會抽取共同的css,如果有共同的js程式碼,也會抽取成為commons.js。
這裡有個有趣的現象,抽取出來的css檔案的命名將會是引數中name的值,而js檔名則會是filename的值。

CommonsChunkPlugin好像只會將所有chunk中都共有的模組抽取出來,如果存在如下的依賴

// entry1.js
var style1 = require(`./style/myStyle.css`)
var style2 = require(`./style/style.css`)

// entry2.js
require("./style/myStyle.css")
require("./style/myStyle2.css")

// entry3.js
require("./style/myStyle2.css")
複製程式碼

使用外掛後會發現,根本沒有生成commons.css檔案。

如果我們只需要取前兩個chunk的共同程式碼,我們可以這麼做

module.exports = {
  entry: {
    "A": "./src/entry.js",
    "B": "./src/entry2.js",
    "C": "./src/entry3.js"
  },
  ...
  plugins: [
    new webpack.optimize.CommonsChunkPlugin({
		name: "commons", filename: "commons.js", chunks: [`A`, `B`]
	}),
    ...
  ]
}
複製程式碼

相關文章