laravel-mix提取Vue組件中的CSS樣式

對于想在 Laravel 項目中提取 Vue 組件中的 CSS 樣式到一個文件中,laravel-mix 的文檔寫得很簡單,只需要添加一行配置項即可:

mix.options({
    extractVueStyles: true
});

然而在實際開發中,我還是遇到了問題。

如果你的Vue組件是全局注冊并且是同步加載的:

Vue.component('example', require('./components/Example.vue'));

那么配置好 extractVueStyles: true 就基本可以了。只不過如果你在某一個組件的 <script> 標簽中通過 import 的方式引入了CSS樣式,那么這部分樣式最終還是會注入到 html 頁面的 <style> 標簽中。

比如我項目中用到了一個社交分享組件,最終 client.css 里面的內容還是無法單獨提取出來:

import Share from "vue-social-share";
import "vue-social-share/dist/client.css";
export default {
  components: {
    Share
  },
  data() {
    return {
      shareConfig: {
        sites: ["qq", "qzone", "weibo"]
      }
    };
  }
};

這只是遇到的第一個問題。其次,由于為了減少白屏時間,我在項目中使用了異步組件的加載方式,這下子上面的方法幾乎就行不通了。

Vue.component('example', () => import('./components/Example.vue'));

這里多說一句,使用異步組件必須安裝 babel-plugin-syntax-dynamic-import 插件,然后在項目根路徑下新建一個 .babelrc 文件添加配置:

{
    "plugins": ["syntax-dynamic-import"]
}

其實,這兩個CSS提取不完整的問題的根本原理是一致的,最終我還是在 vue-cli 的源碼中找到了 ExtractTextPlugin 插件,看一下 allChunks 的定義就很容易明白了:

new ExtractTextPlugin({
  filename: utils.assetsPath('css/[name].[contenthash:8].css'),
  // Setting the following option to `false` will not extract CSS from codesplit chunks.
  // Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack.
  // It's currently set to `true` because we are seeing that sourcemaps are included in the codesplit bundle as well when it's `false`, 
  // increasing file size: https://github.com/vuejs-templates/webpack/issues/1110
  allChunks: true,
}),

原來是 laravel-mix 設計本身的問題,沒有配置這個 allChunks,所以必須需要通過修改源碼的方式來修復。

找到 node_modules\laravel-mix\src\components\Vue.js 文件中的 extractPlugin 方法,傳遞一個對象給構造函數,并加上一條 allChunks: true 直接搞定!

extractPlugin() {
  if (typeof Config.extractVueStyles === 'string') {
      // return new ExtractTextPlugin(this.extractFilePath());
      return new ExtractTextPlugin({
          filename: this.extractFilePath(),
          allChunks: true,
      });
  }
  // ...

注:一般選擇在生產環境下提取CSS即可。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容