Open12

Nuxt2.14.8からextractCSS: true時にpreloadなCSSが吐き出されるから、VuetifyをextractCSSした上でpurgeCSS噛ましてパフォ向上するスレ

meijinmeijin

ファクト

Nuxt内部で使っているこれ
extract-css-chunks-webpack-plugin

以下PRでpreloadが当たるようになった
https://github.com/faceyspacey/extract-css-chunks-webpack-plugin/pull/300/files

もとはといえばmini-css-extract-pluginのこのPRがずっと放置されているのが悪くて、僕も2020年初頭から頭を悩ませていた
https://github.com/webpack-contrib/mini-css-extract-plugin/pull/344

そしたらmini-css-extract-pluginをWrapしている関係性であるextract-css-chunks-webpack-plugin側でやってくれた

Nuxt本丸の方でも議題に上がっていたのね。
https://github.com/nuxt/nuxt.js/issues/8060

長かった。1年以上待ったぞ

extract-css-chunks-webpack-plugin^4.8.0からPreloadされまっせコメント
https://github.com/nuxt/nuxt.js/issues/8060#issuecomment-720142236

なので

自社プロダクトにも導入して、あわよくばVuetifyの余分な大量CSSを省きまくりたいという野望

meijinmeijin

extract-css-chunks-webpack-plugin
自体はNuxt本体をアプデしなくても別途入れたらいいのでnpm i -Dで入れる

meijinmeijin

地道なことをnuxt.config.jsで進めていく。こんなことしなきゃならないのかしら

    extractCSS: true,
    postcss: {
      plugins: {
        '@fullhuman/postcss-purgecss': {
          content: [
            './pages/**/*.vue',
            './layouts/**/*.vue',
            './components/**/*.vue',
          ],
          safelist: [
            /elevation/,
            /transition/,
            /body/,
            /d-/,
            /m(a|r|l|t|b|x|y)-/,
            /p(a|r|l|t|b|x|y)-/,
            /rounded/,
          ],
        },
      },
    },
meijinmeijin

@fullhuman/postcss-purgecss
こっちがv2/v3で結構シンタックス変わっちゃったので、どっち使うか組み合わせを試していく。とりあえずv3で。

meijinmeijin

捕捉

preload CSSにするだけだとVuetifyさんが吐き出す4000ルールものCSSがむしろパフォーマンス悪影響で、Lighthouseスコアが下がった。(手元で10点くらい

下手なCSS大量に吐き出すくらいならJSに入れといたほうがお得という悲しき事実を見た気持ち

meijinmeijin

詰んでいる

Module build failed (from ./node_modules/extract-css-chunks-webpack-plugin/dist/loader.js):
ModuleBuildError: Module build failed (from ./node_modules/postcss-loader/src/index.js):
Error: [object Object] is not a PostCSS plugin
meijinmeijin

以下の設定でできたっぽい。ただちょっと消えすぎている可能性があるためウォークスルーが必要

  purgeCSS: {
    mode: 'webpack',
    enabled: ({ isDev }) => !isDev,
    paths: [
      'components/**/*.vue',
      'layouts/**/*.vue',
      'pages/**/*.vue',
      'plugins/**/*.js',
      'node_modules/vuetify/dist/vuetify.js',
    ],
    extractors: [
      {
        extractor: content => content.match(/[A-Za-z0-9-_:/]+/g) || [],
        extensions: ['html', 'vue', 'js'],
      },
    ],

    // 以下のWhiteList の設定をしなければ、Vuetify のCSS が適用されなくなるので特に注意 !

    whitelist: ['v-application', 'v-application--wrap','layout','row','col'],
    whitelistPatterns: [
      /^v-((?!application).)*$/,
      /^theme--*/,
      /.*-transition/,
      /^justify-*/,
      /^p*-[0-9]/,
      /^m*-[0-9]/,
      /^text--*/,
      /--text$/,
      /^row-*/,
      /^col-*/,
      /^(blue|pink|lime|teal|purple|cyan|indigo|light-blue|orange|pink|amber|grey)$/,
    ],
    whitelistPatternsChildren: [/^v-((?!application).)*$/, /^theme--*/],
  },
meijinmeijin

purgeCSSの設定まあまあしんどい。Global CSSは許せない

meijinmeijin

mode: webpackとextractCSS: true、enabled: trueを組み合わせるのが肝っぽい。

meijinmeijin

purgecssすると手元のLighthouseでLCPが6秒から2秒前半まで縮んだ。CSS削減してpreloadする効果はかなりありそう。