diff --git a/docs/BUNDLERS_INTEGRATION.md b/docs/BUNDLERS_INTEGRATION.md index 58158e94b..905fc4133 100644 --- a/docs/BUNDLERS_INTEGRATION.md +++ b/docs/BUNDLERS_INTEGRATION.md @@ -177,14 +177,6 @@ The loader accepts the following options: Setting this option to `true` will include source maps for the generated CSS so that you can see where source of the class name in devtools. We recommend to enable this only in development mode because the sourcemap is inlined into the CSS files. -- `cacheDirectory: string` (default: `'.linaria-cache'`): - - Path to the directory where the loader will output the intermediate CSS files. You can pass a relative or absolute directory path. Make sure the directory is inside the working directory for things to work properly. **You should add this directory to `.gitignore` so you don't accidentally commit them.** - -- `extension: string` (default: `'.linaria.css'`): - - An extension of the intermediate CSS files. - - `preprocessor: 'none' | 'stylis' | Function` (default: `'stylis'`) You can override the pre-processor if you want to override how the loader processes the CSS. @@ -218,7 +210,6 @@ You can pass options to the loader like so: loader: '@linaria/webpack-loader', options: { sourceMap: false, - cacheDirectory: '.linaria-cache', }, } ``` diff --git a/packages/webpack4-loader/package.json b/packages/webpack4-loader/package.json index 3ed2ce2dd..9c190d379 100644 --- a/packages/webpack4-loader/package.json +++ b/packages/webpack4-loader/package.json @@ -38,22 +38,17 @@ "watch": "yarn build --watch" }, "devDependencies": { - "@types/cosmiconfig": "^5.0.3", "@types/enhanced-resolve": "^3.0.6", "@types/loader-utils": "^1.1.3", "@types/mkdirp": "^0.5.2", - "@types/normalize-path": "^3.0.0", "source-map": "^0.7.3" }, "dependencies": { "@linaria/babel-preset": "^3.0.0-beta.15", "@linaria/logger": "^3.0.0-beta.15", - "cosmiconfig": "^5.1.0", "enhanced-resolve": "^4.1.0", - "find-yarn-workspace-root": "^1.2.1", "loader-utils": "^1.2.3", - "mkdirp": "^0.5.1", - "normalize-path": "^3.0.0" + "mkdirp": "^0.5.1" }, "peerDependencies": { "@babel/core": ">=7" diff --git a/packages/webpack4-loader/src/index.ts b/packages/webpack4-loader/src/index.ts index 3a4848e26..7edfb061f 100644 --- a/packages/webpack4-loader/src/index.ts +++ b/packages/webpack4-loader/src/index.ts @@ -4,24 +4,13 @@ * returns transformed code without template literals and attaches generated source maps */ -import fs from 'fs'; import path from 'path'; -import mkdirp from 'mkdirp'; -import normalize from 'normalize-path'; import loaderUtils from 'loader-utils'; import enhancedResolve from 'enhanced-resolve'; -import findYarnWorkspaceRoot from 'find-yarn-workspace-root'; import type { RawSourceMap } from 'source-map'; -import cosmiconfig from 'cosmiconfig'; import { EvalCache, Module, transform } from '@linaria/babel-preset'; import { debug, notify } from '@linaria/logger'; - -const workspaceRoot = findYarnWorkspaceRoot(); -const lernaConfig = cosmiconfig('lerna', { - searchPlaces: ['lerna.json'], -}).searchSync(); -const lernaRoot = - lernaConfig !== null ? path.dirname(lernaConfig.filepath) : null; +import { addFile } from './outputCssLoader'; type LoaderContext = Parameters[0]; @@ -35,6 +24,8 @@ const castSourceMap = ( } : undefined; +const outputCssLoader = require.resolve('./outputCssLoader'); + export default function webpack4Loader( this: LoaderContext, content: string, @@ -51,28 +42,11 @@ export default function webpack4Loader( const { sourceMap = undefined, - cacheDirectory = '.linaria-cache', preprocessor = undefined, - extension = '.linaria.css', resolveOptions = {}, ...rest } = loaderUtils.getOptions(this) || {}; - const root = workspaceRoot || lernaRoot || process.cwd(); - - const baseOutputFileName = this.resourcePath.replace(/\.[^.]+$/, extension); - - const outputFilename = normalize( - path.join( - path.isAbsolute(cacheDirectory) - ? cacheDirectory - : path.join(process.cwd(), cacheDirectory), - this.resourcePath.includes(root) - ? path.relative(root, baseOutputFileName) - : baseOutputFileName - ) - ); - // this._compilation is a deprecated API // However there seems to be no other way to access webpack's resolver // There is this.resolve, but it's asynchronous @@ -130,7 +104,6 @@ export default function webpack4Loader( result = transform(content, { filename: path.relative(process.cwd(), this.resourcePath), inputSourceMap: inputSourceMap ?? undefined, - outputFilename, pluginOptions: rest, preprocessor, }); @@ -161,28 +134,14 @@ export default function webpack4Loader( }); } - // Read the file first to compare the content - // Write the new content only if it's changed - // This will prevent unnecessary WDS reloads - let currentCssText; - - try { - currentCssText = fs.readFileSync(outputFilename, 'utf-8'); - } catch (e) { - // Ignore error - } + addFile(this.resourcePath, cssText); - if (currentCssText !== cssText) { - mkdirp.sync(path.dirname(outputFilename)); - fs.writeFileSync(outputFilename, cssText); - } + const request = `linaria.css!=!${outputCssLoader}!${this.resourcePath}`; + const stringifiedRequest = loaderUtils.stringifyRequest(this, request); this.callback( null, - `${result.code}\n\nrequire(${loaderUtils.stringifyRequest( - this, - outputFilename - )});`, + `${result.code}\n\nrequire(${stringifiedRequest});`, castSourceMap(result.sourceMap) ); return; diff --git a/packages/webpack4-loader/src/outputCssLoader.ts b/packages/webpack4-loader/src/outputCssLoader.ts new file mode 100644 index 000000000..39df29f7c --- /dev/null +++ b/packages/webpack4-loader/src/outputCssLoader.ts @@ -0,0 +1,9 @@ +const cssLookup = new Map(); + +export const addFile = (id: string, content: string) => { + cssLookup.set(id, content); +}; + +export default async function outputCssLoader(this: { resourcePath: string }) { + return cssLookup.get(this.resourcePath) ?? ''; +} diff --git a/packages/webpack5-loader/package.json b/packages/webpack5-loader/package.json index 12480c199..58a78d1fa 100644 --- a/packages/webpack5-loader/package.json +++ b/packages/webpack5-loader/package.json @@ -38,23 +38,18 @@ "watch": "yarn build --watch" }, "devDependencies": { - "@types/cosmiconfig": "^5.0.3", "@types/enhanced-resolve": "^3.0.6", "@types/loader-utils": "^1.1.3", "@types/mkdirp": "^0.5.2", - "@types/normalize-path": "^3.0.0", "source-map": "^0.7.3", "webpack": "^5.6.0" }, "dependencies": { "@linaria/babel-preset": "^3.0.0-beta.15", "@linaria/logger": "^3.0.0-beta.15", - "cosmiconfig": "^5.1.0", "enhanced-resolve": "^5.3.1", - "find-yarn-workspace-root": "^1.2.1", "loader-utils": "^2.0.0", - "mkdirp": "^0.5.1", - "normalize-path": "^3.0.0" + "mkdirp": "^0.5.1" }, "peerDependencies": { "@babel/core": ">=7", diff --git a/packages/webpack5-loader/src/index.ts b/packages/webpack5-loader/src/index.ts index 7d100aede..257138575 100644 --- a/packages/webpack5-loader/src/index.ts +++ b/packages/webpack5-loader/src/index.ts @@ -4,24 +4,15 @@ * returns transformed code without template literals and attaches generated source maps */ -import fs from 'fs'; import path from 'path'; import loaderUtils from 'loader-utils'; -import mkdirp from 'mkdirp'; -import normalize from 'normalize-path'; import enhancedResolve from 'enhanced-resolve'; -import findYarnWorkspaceRoot from 'find-yarn-workspace-root'; import type { RawSourceMap } from 'source-map'; -import cosmiconfig from 'cosmiconfig'; import { EvalCache, Module, transform } from '@linaria/babel-preset'; import { debug, notify } from '@linaria/logger'; +import { addFile } from './outputCssLoader'; -const workspaceRoot = findYarnWorkspaceRoot(); -const lernaConfig = cosmiconfig('lerna', { - searchPlaces: ['lerna.json'], -}).searchSync(); -const lernaRoot = - lernaConfig !== null ? path.dirname(lernaConfig.filepath) : null; +const outputCssLoader = require.resolve('./outputCssLoader'); export default function webpack5Loader( this: any, @@ -39,28 +30,11 @@ export default function webpack5Loader( const { sourceMap = undefined, - cacheDirectory = '.linaria-cache', preprocessor = undefined, - extension = '.linaria.css', resolveOptions = {}, ...rest } = this.getOptions() || {}; - const root = workspaceRoot || lernaRoot || process.cwd(); - - const baseOutputFileName = this.resourcePath.replace(/\.[^.]+$/, extension); - - const outputFilename = normalize( - path.join( - path.isAbsolute(cacheDirectory) - ? cacheDirectory - : path.join(process.cwd(), cacheDirectory), - this.resourcePath.includes(root) - ? path.relative(root, baseOutputFileName) - : baseOutputFileName - ) - ); - // this._compilation is a deprecated API // However there seems to be no other way to access webpack's resolver // There is this.resolve, but it's asynchronous @@ -123,7 +97,6 @@ export default function webpack5Loader( result = transform(content, { filename: path.relative(process.cwd(), this.resourcePath), inputSourceMap: inputSourceMap ?? undefined, - outputFilename, pluginOptions: rest, preprocessor, }); @@ -154,28 +127,14 @@ export default function webpack5Loader( }); } - // Read the file first to compare the content - // Write the new content only if it's changed - // This will prevent unnecessary WDS reloads - let currentCssText; + addFile(this.resourcePath, cssText); - try { - currentCssText = fs.readFileSync(outputFilename, 'utf-8'); - } catch (e) { - // Ignore error - } - - if (currentCssText !== cssText) { - mkdirp.sync(path.dirname(outputFilename)); - fs.writeFileSync(outputFilename, cssText); - } + const request = `linaria.css!=!${outputCssLoader}!${this.resourcePath}`; + const stringifiedRequest = loaderUtils.stringifyRequest(this, request); this.callback( null, - `${result.code}\n\nrequire(${loaderUtils.stringifyRequest( - this, - outputFilename - )});`, + `${result.code}\n\nrequire(${stringifiedRequest});`, result.sourceMap ?? undefined ); return; diff --git a/packages/webpack5-loader/src/outputCssLoader.ts b/packages/webpack5-loader/src/outputCssLoader.ts new file mode 100644 index 000000000..39df29f7c --- /dev/null +++ b/packages/webpack5-loader/src/outputCssLoader.ts @@ -0,0 +1,9 @@ +const cssLookup = new Map(); + +export const addFile = (id: string, content: string) => { + cssLookup.set(id, content); +}; + +export default async function outputCssLoader(this: { resourcePath: string }) { + return cssLookup.get(this.resourcePath) ?? ''; +}