diff --git a/build.config.mjs b/build.config.mjs index a96a13a227..e158ad9e9e 100644 --- a/build.config.mjs +++ b/build.config.mjs @@ -10,7 +10,6 @@ export default { // package '@nuxt/image', - '@nuxtjs/critters', 'browserslist-useragent-regexp', 'cheerio', 'defu', diff --git a/docs/src/guide/options.md b/docs/src/guide/options.md index 5ca978599f..d329dad5a4 100644 --- a/docs/src/guide/options.md +++ b/docs/src/guide/options.md @@ -254,21 +254,6 @@ Global option for the [`IntersectionObserver`](https://developer.mozilla.org/en- | `component` | `String` | yes | [`rootMargin`](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver/rootMargin) value for [`SpeedkitHydrate`](/guide/usage#import-components). | `0%` | | `asset` | `String` | yes | [`rootMargin`](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver/rootMargin) value for all static ressources (`v-font`, `SpeedkitPicture` & `SpeedkitImage`). | `0%` | -## `disableNuxtCritters` - -- Type: `Boolean` - - Default: `false` - -If set, `@nuxtjs/critters` will not be integrated. - -::: danger -⚠️ Note that CSS is not embedded in the page. -::: - -::: info -For more information: -::: - ## `disableNuxtFontaine` - Type: `Boolean` diff --git a/package-lock.json b/package-lock.json index 0f75c90ef9..c8466282c2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,6 @@ "license": "MIT", "dependencies": { "@nuxt/image": "1.0.0", - "@nuxtjs/critters": "0.5.1", "@nuxtjs/fontaine": "0.4.1", "browserslist-useragent-regexp": "4.1.0", "cheerio": "1.0.0-rc.12", @@ -4624,92 +4623,6 @@ "integrity": "sha512-KnaMTE6EItz/f2q4Gwg5/rmeKVi79OR58NoYnwDJqCk9ywMtTGbBnBcfoBtN4QbYu0lWXvyMoH2Owxuhe4qI6Q==", "dev": true }, - "node_modules/@nuxtjs/critters": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/@nuxtjs/critters/-/critters-0.5.1.tgz", - "integrity": "sha512-TxrPVX51dV6OOhXmgDkYnPefSx3BPoOgPI0mXiGJcg9hD2rpytDJ67YGFDFygL+k2MBBJhELklOApMl1XdTdKQ==", - "dependencies": { - "@nuxt/kit": "3.6.5", - "critters": "0.0.20", - "pathe": "1.1.1" - } - }, - "node_modules/@nuxtjs/critters/node_modules/@nuxt/kit": { - "version": "3.6.5", - "resolved": "https://registry.npmjs.org/@nuxt/kit/-/kit-3.6.5.tgz", - "integrity": "sha512-uBI5I2Zx6sk+vRHU+nBmifwxg/nyXCGZ1g5hUKrUfgv1ZfiKB8JkN5T9iRoduDOaqbwM6XSnEl1ja73iloDcrw==", - "dependencies": { - "@nuxt/schema": "3.6.5", - "c12": "^1.4.2", - "consola": "^3.2.3", - "defu": "^6.1.2", - "globby": "^13.2.2", - "hash-sum": "^2.0.0", - "ignore": "^5.2.4", - "jiti": "^1.19.1", - "knitwork": "^1.0.0", - "mlly": "^1.4.0", - "pathe": "^1.1.1", - "pkg-types": "^1.0.3", - "scule": "^1.0.0", - "semver": "^7.5.3", - "unctx": "^2.3.1", - "unimport": "^3.0.14", - "untyped": "^1.3.2" - }, - "engines": { - "node": "^14.18.0 || >=16.10.0" - } - }, - "node_modules/@nuxtjs/critters/node_modules/@nuxt/schema": { - "version": "3.6.5", - "resolved": "https://registry.npmjs.org/@nuxt/schema/-/schema-3.6.5.tgz", - "integrity": "sha512-UPUnMB0W5TZ/Pi1fiF71EqIsPlj8LGZqzhSf8wOeh538KHwxbA9r7cuvEUU92eXRksOZaylbea3fJxZWhOITVw==", - "dependencies": { - "defu": "^6.1.2", - "hookable": "^5.5.3", - "pathe": "^1.1.1", - "pkg-types": "^1.0.3", - "postcss-import-resolver": "^2.0.0", - "std-env": "^3.3.3", - "ufo": "^1.1.2", - "unimport": "^3.0.14", - "untyped": "^1.3.2" - }, - "engines": { - "node": "^14.18.0 || >=16.10.0" - } - }, - "node_modules/@nuxtjs/critters/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@nuxtjs/critters/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@nuxtjs/critters/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, "node_modules/@nuxtjs/eslint-config": { "version": "12.0.0", "resolved": "https://registry.npmjs.org/@nuxtjs/eslint-config/-/eslint-config-12.0.0.tgz", @@ -8152,7 +8065,8 @@ "node_modules/core-util-is": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true }, "node_modules/cosmiconfig": { "version": "8.3.6", @@ -8228,113 +8142,6 @@ "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", "dev": true }, - "node_modules/critters": { - "version": "0.0.20", - "resolved": "https://registry.npmjs.org/critters/-/critters-0.0.20.tgz", - "integrity": "sha512-CImNRorKOl5d8TWcnAz5n5izQ6HFsvz29k327/ELy6UFcmbiZNOsinaKvzv16WZR0P6etfSWYzE47C4/56B3Uw==", - "dependencies": { - "chalk": "^4.1.0", - "css-select": "^5.1.0", - "dom-serializer": "^2.0.0", - "domhandler": "^5.0.2", - "htmlparser2": "^8.0.2", - "postcss": "^8.4.23", - "pretty-bytes": "^5.3.0" - } - }, - "node_modules/critters/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/critters/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/critters/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/critters/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "node_modules/critters/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/critters/node_modules/htmlparser2": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", - "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==", - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3", - "domutils": "^3.0.1", - "entities": "^4.4.0" - } - }, - "node_modules/critters/node_modules/pretty-bytes": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", - "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/critters/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/cross-fetch": { "version": "3.1.6", "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.6.tgz", @@ -9404,6 +9211,7 @@ "version": "0.1.8", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", + "dev": true, "dependencies": { "prr": "~1.0.1" }, @@ -12007,7 +11815,8 @@ "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true }, "node_modules/graphemer": { "version": "1.4.0", @@ -12507,7 +12316,8 @@ "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "devOptional": true }, "node_modules/ini": { "version": "1.3.8", @@ -13100,7 +12910,8 @@ "node_modules/isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true }, "node_modules/isexe": { "version": "2.0.0", @@ -14541,6 +14352,7 @@ "version": "0.5.0", "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", + "dev": true, "dependencies": { "errno": "^0.1.3", "readable-stream": "^2.0.1" @@ -14553,6 +14365,7 @@ "version": "2.3.8", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -14566,12 +14379,14 @@ "node_modules/memory-fs/node_modules/safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true }, "node_modules/memory-fs/node_modules/string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, "dependencies": { "safe-buffer": "~5.1.0" } @@ -17270,6 +17085,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/postcss-import-resolver/-/postcss-import-resolver-2.0.0.tgz", "integrity": "sha512-y001XYgGvVwgxyxw9J1a5kqM/vtmIQGzx34g0A0Oy44MFcy/ZboZw1hu/iN3VYFjSTRzbvd7zZJJz0Kh0AGkTw==", + "dev": true, "dependencies": { "enhanced-resolve": "^4.1.1" } @@ -17278,6 +17094,7 @@ "version": "4.5.0", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz", "integrity": "sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg==", + "dev": true, "dependencies": { "graceful-fs": "^4.1.2", "memory-fs": "^0.5.0", @@ -17291,6 +17108,7 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", + "dev": true, "engines": { "node": ">=6" } @@ -18291,7 +18109,8 @@ "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true }, "node_modules/promise": { "version": "7.3.1", @@ -18344,7 +18163,8 @@ "node_modules/prr": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==" + "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==", + "dev": true }, "node_modules/psl": { "version": "1.9.0", @@ -22097,7 +21917,8 @@ "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "devOptional": true }, "node_modules/validate-npm-package-license": { "version": "3.0.4", diff --git a/package.json b/package.json index d0252facbc..b648b42d0b 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,6 @@ ], "dependencies": { "@nuxt/image": "1.0.0", - "@nuxtjs/critters": "0.5.1", "@nuxtjs/fontaine": "0.4.1", "browserslist-useragent-regexp": "4.1.0", "cheerio": "1.0.0-rc.12", diff --git a/src/hookFunctions/nitro/init.mjs b/src/hookFunctions/nitro/init.mjs index b031dead63..65dbe92333 100644 --- a/src/hookFunctions/nitro/init.mjs +++ b/src/hookFunctions/nitro/init.mjs @@ -3,79 +3,44 @@ import { basename, dirname, join, resolve } from 'pathe'; import { parseDocument } from 'htmlparser2'; import { load } from 'cheerio'; import { render } from 'dom-serializer'; -import { logger } from '../../utils.mjs'; +import { isWebpackBuild, logger } from '../../utils.mjs'; -export default (nuxt, disableNuxtCritters = true) => +export default (nuxt, options = { manifest: [] }) => nitro => { nitro.hooks.hook('prerender:generate', async route => { + const { manifest } = options; + if (!route.fileName?.endsWith('.html') || !route.contents) { return; } + // https://nuxt.com/docs/guide/directory-structure/output + const distNuxt = join( + nuxt.options.buildDir, + 'dist/client', + nuxt.options.app.buildAssetsDir + ); + const document = parseDocument(route.contents); const $ = load(document); + // webpack workaround inline css in ssr + if (isWebpackBuild(nuxt)) { + await addedInlinedCSS($, getCSSFilesFromManifest($, manifest), { + distNuxt, + route + }); + } + $('[rel="modulepreload"][as="script"]').remove(); $('[rel="prefetch"][as="script"]').remove(); + $('[rel="preload"][as="fetch"]').remove(); $('[rel="preload"][as="style"]').remove(); $('[rel="prefetch"][as="style"]').remove(); // embed css files - try { - const css = await Promise.all( - Array.from($('link[rel="stylesheet"]')) - .map(el => $(el)) - .filter($el => !isURL($el.attr('href'))) - .map(async $el => { - const dir = dirname($el.attr('href')); - - // https://nuxt.com/docs/guide/directory-structure/output - const distNuxt = join( - nuxt.options.buildDir, - 'dist/client', - nuxt.options.app.buildAssetsDir - ); - const filepath = join(distNuxt, basename($el.attr('href'))); - const fileContent = await fsPromises.readFile(filepath, 'utf-8'); - - let urls = getUrlValues(fileContent); - urls = prepareUrls(urls, dir); - - if (disableNuxtCritters) { - const css = urls.reduce( - (result, [a, b]) => result.replace(a, b), - fileContent - ); - - $el.remove(); - logger.info( - `Embed CSS File \`${basename($el.attr('href'))}\`; Route: \`${ - route.route - }\`` - ); - return css; - } else { - const matches = fileContent.match( - /\/\*! speedkit-font-faces start \*\/(.*)\/\*! speedkit-font-faces end \*\// - ); - if (matches) { - logger.info( - `Embed Font-Faces CSS \`${basename( - $el.attr('href') - )}\`; Route: \`${route.route}\`` - ); - return matches[1].replace(/url\(.\//g, `url(${dir}/`); - } - } - }) - ); - if (css.length) { - $('head').append(``); - } - } catch (error) { - logger.error("can't embed css file.", error); - } + await prepareLinkStylesheets($, { distNuxt, route }); route.contents = render(document); }); @@ -106,3 +71,73 @@ function isURL(value) { function isDataURI(value) { return value.startsWith('data:'); } + +async function prepareLinkStylesheets($, { distNuxt, route }) { + try { + const css = await Promise.all( + Array.from($('link[rel="stylesheet"]')) + .map(el => $(el)) + .filter($el => !isURL($el.attr('href'))) + .map(async $el => { + const dir = dirname($el.attr('href')); + const filepath = join(distNuxt, basename($el.attr('href'))); + // eslint-disable-next-line security/detect-non-literal-fs-filename + const fileContent = await fsPromises.readFile(filepath, 'utf-8'); + + let urls = getUrlValues(fileContent); + urls = prepareUrls(urls, dir); + + const css = urls.reduce( + (result, [a, b]) => result.replace(a, b), + fileContent + ); + + $el.remove(); + logger.info( + `Embed CSS File \`${basename($el.attr('href'))}\`; Route: \`${ + route.route + }\`` + ); + return css; + }) + ); + if (css.length) { + $('head').append(``); + } + } catch (error) { + logger.error("can't embed css file.", error); + } +} + +function getCSSFilesFromManifest($, manifest) { + const scripts = Array.from($('script[type="module"]')); + return scripts + .map(el => { + return ( + manifest[String(`_${basename($(el).attr('src'))}`)]?.dynamicImports || + [] + ); + }) + .flat() + .filter(file => file.endsWith('.css')) + .map(file => `${basename(file)}`); +} + +async function addedInlinedCSS($, files, { distNuxt, route }) { + const css = await Promise.all( + files.map(async filename => { + // eslint-disable-next-line security/detect-non-literal-fs-filename + const css = await fsPromises.readFile( + join(distNuxt, 'css', filename), + 'utf-8' + ); + logger.info( + `Embed CSS File \`${basename(filename)}\`; Route: \`${route.route}\`` + ); + return css; + }) + ); + if (css.length) { + $('head').append(``); + } +} diff --git a/src/module.mjs b/src/module.mjs index 82dbe4d217..8caf9acae7 100644 --- a/src/module.mjs +++ b/src/module.mjs @@ -11,14 +11,16 @@ import FontConfig from './runtime/classes/FontConfig.mjs'; import { DEFAULT_TARGET_FORMATS, MODULE_NAME, - addNuxtCritters, addNuxtFontaine, addNuxtImage, isWebpackBuild, logger, setPublicRuntimeConfig } from './utils.mjs'; -import { getDefaultOptions } from './utils/options.mjs'; +import { + deprecationsNotification, + getDefaultOptions +} from './utils/options.mjs'; import { getFontConfigTemplate } from './utils/template.mjs'; import { optimizePreloads } from './utils/preload.mjs'; import { getSupportedBrowserDetector } from './utils/browser.mjs'; @@ -42,17 +44,12 @@ export default defineNuxtModule({ nuxt.options.alias['#speedkit'] = runtimeDir; nuxt.options.build.transpile.push(runtimeDir); + deprecationsNotification(moduleOptions); + await addModules(nuxt, moduleOptions); setPublicRuntimeConfig(nuxt, moduleOptions); - // TODO: Remove in future - if (isWebpackBuild(nuxt)) { - logger.warn( - `[${MODULE_NAME}]: Webpack build is not usable yet.\nOpen Issues:\n- Inline Styles (\`https://nuxt.com/docs/api/configuration/nuxt-config#inlinessrstyles\`)` - ); - } - if (moduleOptions.detection.performance && nuxt.options.ssr) { if (isWebpackBuild(nuxt)) { nuxt.hook( @@ -148,9 +145,6 @@ async function addBuildTemplates(nuxt, options) { } async function addModules(nuxt, moduleOptions) { - if (!moduleOptions.disableNuxtCritters) { - await addNuxtCritters(nuxt); - } if (!moduleOptions.disableNuxtFontaine) { await addNuxtFontaine(nuxt); } diff --git a/src/utils.mjs b/src/utils.mjs index aff32166d2..f7a53eae38 100644 --- a/src/utils.mjs +++ b/src/utils.mjs @@ -36,29 +36,10 @@ function moduleExists(nuxt, moduleName) { ); } -export async function addNuxtCritters(nuxt) { - if (!moduleExists(nuxt, '@nuxtjs/critters')) { - logger.info( - `[${MODULE_NAME}] added module \`@nuxtjs/critters\`, for more configuration learn more at \`https://github.com/nuxt-modules/critters\`` - ); - nuxt.options.critters = defu( - { - config: { - preload: false, - fonts: false - } - }, - nuxt.options.critters - ); - - await installModule('@nuxtjs/critters'); - } -} - export async function addNuxtFontaine(nuxt) { if (!moduleExists(nuxt, '@nuxtjs/fontaine')) { logger.info( - `[${MODULE_NAME}] added module \`@nuxtjs/fontaine\`, for more configuration learn more at \`https://github.com/nuxt-modules/fontaine\`` + `Added module \`@nuxtjs/fontaine\`, for more configuration learn more at \`https://github.com/nuxt-modules/fontaine\`` ); await installModule('@nuxtjs/fontaine'); } @@ -67,7 +48,7 @@ export async function addNuxtFontaine(nuxt) { export async function addNuxtImage(nuxt) { if (!moduleExists(nuxt, '@nuxt/image')) { logger.info( - `[${MODULE_NAME}] added module \`@nuxt/image\`, for more configuration learn more at \`https://image.nuxtjs.org/setup#configure\`` + `Added module \`@nuxt/image\`, for more configuration learn more at \`https://image.nuxtjs.org/setup#configure\`` ); await installModule('@nuxt/image'); } diff --git a/src/utils/options.mjs b/src/utils/options.mjs index 63582422ab..594a07d150 100644 --- a/src/utils/options.mjs +++ b/src/utils/options.mjs @@ -1,4 +1,4 @@ -import { MODULE_NAME, logger } from '../utils.mjs'; +import { logger } from '../utils.mjs'; export function getDefaultOptions() { return { @@ -6,7 +6,6 @@ export function getDefaultOptions() { crossorigin: undefined, - disableNuxtCritters: true, // If set, `@nuxtjs/critters` will not be integrated. disableNuxtFontaine: false, // If set, `@nuxtjs/fontaine` will not be integrated. disableNuxtImage: false, // If set, `@nuxt/image` will not be integrated. @@ -42,7 +41,13 @@ export function getDefaultOptions() { export function deprecationsNotification(options) { if ('loader' in options) { logger.warn( - `[${MODULE_NAME}] Option \`loader\` is deprecated, There is no integrated loader anymore.` + 'Option `loader` is deprecated, there is no integrated loader anymore.' + ); + delete options.loader; + } + if ('disableNuxtCritters' in options) { + logger.warn( + 'Option `disableNuxtCritters` is deprecated, there is no integrated critters anymore.' ); delete options.loader; } diff --git a/src/utils/preload.mjs b/src/utils/preload.mjs index 567083da4e..bcc57ecb86 100644 --- a/src/utils/preload.mjs +++ b/src/utils/preload.mjs @@ -1,17 +1,20 @@ import initHook from '../hookFunctions/nitro/init.mjs'; -import { isViteBuild } from '../utils.mjs'; +import { isViteBuild, isWebpackBuild, logger } from '../utils.mjs'; export function optimizePreloads(moduleOptions, nuxt) { - const disableNuxtCritters = moduleOptions.disableNuxtCritters; + nuxt.options.experimental.inlineSSRStyles = false; if (isViteBuild(nuxt)) { nuxt.options.vite.build.manifest = false; - if (disableNuxtCritters) { - nuxt.options.vite.build.cssCodeSplit = false; - } + nuxt.options.vite.build.cssCodeSplit = false; + } else if (isWebpackBuild(nuxt)) { + nuxt.options.webpack.extractCSS = true; + logger.info(`Use workaround for \`SSR Styles\` in \`Webpack\`.`); } - nuxt.options.experimental.inlineSSRStyles = false; - - nuxt.hook('nitro:init', initHook(nuxt, disableNuxtCritters)); + const hookOptions = { + manifest: null + }; + nuxt.hook('build:manifest', manifest => (hookOptions.manifest = manifest)); + nuxt.hook('nitro:init', initHook(nuxt, hookOptions)); }