diff --git a/.changeset/css-side-effect-imports-hmr-cache.md b/.changeset/css-side-effect-imports-hmr-cache.md new file mode 100644 index 00000000000..8bfede70936 --- /dev/null +++ b/.changeset/css-side-effect-imports-hmr-cache.md @@ -0,0 +1,5 @@ +--- +"@remix-run/dev": patch +--- + +Cache CSS side-effect imports transform when using HMR diff --git a/packages/remix-dev/compiler/plugins/cssSideEffectImports.ts b/packages/remix-dev/compiler/plugins/cssSideEffectImports.ts index c81e575018f..87d51f7e11e 100644 --- a/packages/remix-dev/compiler/plugins/cssSideEffectImports.ts +++ b/packages/remix-dev/compiler/plugins/cssSideEffectImports.ts @@ -1,7 +1,6 @@ import path from "path"; import type { Plugin } from "esbuild"; import fse from "fs-extra"; -import LRUCache from "lru-cache"; import { parse, type ParserOptions } from "@babel/parser"; import traverse from "@babel/traverse"; import generate from "@babel/generator"; @@ -56,28 +55,52 @@ export const cssSideEffectImportsPlugin = ( build.onLoad( { filter: allJsFilesFilter, namespace: "file" }, async (args) => { - let code = await fse.readFile(args.path, "utf8"); - - // Don't process file if it doesn't contain any references to CSS files - if (!code.includes(".css")) { + let cacheKey = `css-side-effect-imports-plugin:${args.path}&hmr=${hmr}`; + let { cacheValue } = await ctx.fileWatchCache.getOrSet( + cacheKey, + async () => { + let fileDependencies = new Set([args.path]); + + let code = await fse.readFile(args.path, "utf8"); + + // Don't process file if it doesn't contain any references to CSS files + if (!code.includes(".css")) { + return { + fileDependencies, + cacheValue: null, + }; + } + + let loader = + loaderForExtension[path.extname(args.path) as Extension]; + let contents = addSuffixToCssSideEffectImports(loader, code); + + if (args.path.startsWith(ctx.config.appDirectory) && hmr) { + contents = await applyHMR( + contents, + args, + ctx.config, + !!build.initialOptions.sourcemap + ); + } + + return { + fileDependencies, + cacheValue: { + contents, + loader, + }, + }; + } + ); + + if (!cacheValue) { return null; } - let loader = loaderForExtension[path.extname(args.path) as Extension]; - let contents = addSuffixToCssSideEffectImports(loader, code); - - if (args.path.startsWith(ctx.config.appDirectory) && hmr) { - contents = await applyHMR( - contents, - args, - ctx.config, - !!build.initialOptions.sourcemap - ); - } - return { - contents, - loader, + contents: cacheValue.contents, + loader: cacheValue.loader, }; } ); @@ -129,20 +152,10 @@ const babelPluginsForLoader: Record = { tsx: ["typescript", "jsx", ...additionalLanguageFeatures], }; -const cache = new LRUCache({ max: 1000 }); -const getCacheKey = (loader: Loader, code: string) => `${loader}:${code}`; - export function addSuffixToCssSideEffectImports( loader: Loader, code: string ): string { - let cacheKey = getCacheKey(loader, code); - let cachedResult = cache.get(cacheKey); - - if (cachedResult) { - return cachedResult; - } - let ast = parse(code, { sourceType: "module", plugins: babelPluginsForLoader[loader], @@ -192,7 +205,5 @@ export function addSuffixToCssSideEffectImports( compact: false, }).code; - cache.set(cacheKey, result); - return result; } diff --git a/packages/remix-dev/package.json b/packages/remix-dev/package.json index 9d35c2688d2..1a007909273 100644 --- a/packages/remix-dev/package.json +++ b/packages/remix-dev/package.json @@ -49,7 +49,6 @@ "json5": "^2.2.2", "lodash": "^4.17.21", "lodash.debounce": "^4.0.8", - "lru-cache": "^7.14.1", "minimatch": "^9.0.0", "node-fetch": "^2.6.9", "ora": "^5.4.1", diff --git a/yarn.lock b/yarn.lock index 759d35eccd3..e029775c2d4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9487,11 +9487,6 @@ lru-cache@^6.0.0: dependencies: yallist "^4.0.0" -lru-cache@^7.14.1: - version "7.14.1" - resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-7.14.1.tgz" - integrity sha512-ysxwsnTKdAx96aTRdhDOCQfDgbHnt8SK0KY8SEjO0wHinhWOFTESbjVCMPbU1uGXg/ch4lifqx0wfjOawU2+WA== - lz-string@^1.4.4: version "1.4.4" resolved "https://registry.npmjs.org/lz-string/-/lz-string-1.4.4.tgz"