From 4f2923dab1e2f58d33697aa2a5b7a44fb0585205 Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Tue, 26 Oct 2021 17:51:56 +0300 Subject: [PATCH] refactor: future build `@import` --- src/index.js | 4 +- src/plugins/postcss-import-parser.js | 41 ++++++--- src/plugins/postcss-url-parser.js | 83 +++++++++++------- src/utils.js | 37 +++++--- test/__snapshots__/import-option.test.js.snap | 72 +++++++++++++++ test/__snapshots__/url-option.test.js.snap | 5 -- test/fixtures/import/absolute-url.css | 5 ++ test/fixtures/import/absolute-url.js | 5 ++ test/fixtures/import/data-uri.css | 6 ++ test/fixtures/import/data-uri.js | 5 ++ test/fixtures/url/absolute-url.css | 2 - test/import-option.test.js | 43 +++++++++ ..._fixtures_url_img_fc0003ff99956138ca55.png | Bin test/lock-files/import/lock.json | 15 ++++ test/lock-files/lock.json | 7 -- test/url-option.test.js | 7 +- 16 files changed, 259 insertions(+), 78 deletions(-) create mode 100644 test/fixtures/import/absolute-url.css create mode 100644 test/fixtures/import/absolute-url.js create mode 100644 test/fixtures/import/data-uri.css create mode 100644 test/fixtures/import/data-uri.js rename test/lock-files/{ => import}/https_raw.githubusercontent.com/webpack-contrib_css-loader_master_test_fixtures_url_img_fc0003ff99956138ca55.png (100%) create mode 100644 test/lock-files/import/lock.json delete mode 100644 test/lock-files/lock.json diff --git a/src/index.js b/src/index.js index 7208d91f..e52261fd 100644 --- a/src/index.js +++ b/src/index.js @@ -71,7 +71,8 @@ export default async function loader(content, map, meta) { if (shouldUseImportPlugin(options)) { plugins.push( importParser({ - isSupportAbsoluteURL, + isSupportAbsoluteURL: false, + isSupportDataURL: false, isCSSStyleSheet: options.exportType === "css-style-sheet", loaderContext: this, imports: importPluginImports, @@ -100,7 +101,6 @@ export default async function loader(content, map, meta) { context: this.context, rootContext: this.rootContext, filter: getFilter(options.url.filter, this.resourcePath), - needToResolveURL, resolver: needToResolveURL ? this.getResolve({ mainFiles: [], extensions: [] }) : // eslint-disable-next-line no-undefined diff --git a/src/plugins/postcss-import-parser.js b/src/plugins/postcss-import-parser.js index 5527fa6e..6e57379f 100644 --- a/src/plugins/postcss-import-parser.js +++ b/src/plugins/postcss-import-parser.js @@ -3,12 +3,12 @@ import valueParser from "postcss-value-parser"; import { normalizeUrl, resolveRequests, - isUrlRequestable, + isURLRequestable, requestify, WEBPACK_IGNORE_COMMENT_REGEXP, } from "../utils"; -function parseNode(atRule, key) { +function parseNode(atRule, key, options) { // Convert only top-level @import if (atRule.parent.type !== "root") { return; @@ -97,10 +97,11 @@ function parseNode(atRule, key) { url = normalizeUrl(url, isStringValue); - const isRequestable = isUrlRequestable(url); + const { requestable, needResolve } = isURLRequestable(url, options); + let prefix; - if (isRequestable) { + if (requestable && needResolve) { const queryParts = url.split("!"); if (queryParts.length > 1) { @@ -165,7 +166,16 @@ function parseNode(atRule, key) { } // eslint-disable-next-line consistent-return - return { atRule, prefix, url, layer, supports, media, isRequestable }; + return { + atRule, + prefix, + url, + layer, + supports, + media, + requestable, + needResolve, + }; } const plugin = (options = {}) => { @@ -189,10 +199,15 @@ const plugin = (options = {}) => { return; } + const { isSupportDataURL, isSupportAbsoluteURL } = options; + let parsedAtRule; try { - parsedAtRule = parseNode(atRule, "params", result); + parsedAtRule = parseNode(atRule, "params", { + isSupportAbsoluteURL, + isSupportDataURL, + }); } catch (error) { result.warn(error.message, { node: error.node }); } @@ -223,7 +238,8 @@ const plugin = (options = {}) => { parsedAtRules.map(async (parsedAtRule) => { const { atRule, - isRequestable, + requestable, + needResolve, prefix, url, layer, @@ -245,7 +261,7 @@ const plugin = (options = {}) => { } } - if (isRequestable) { + if (needResolve) { const request = requestify(url, loaderContext.rootContext); const resolvedUrl = await resolveRequests( resolver, @@ -272,14 +288,14 @@ const plugin = (options = {}) => { supports, media, prefix, - isRequestable, + requestable, }; } atRule.remove(); // eslint-disable-next-line consistent-return - return { url, layer, supports, media, prefix, isRequestable }; + return { url, layer, supports, media, prefix, requestable }; }) ); @@ -293,10 +309,9 @@ const plugin = (options = {}) => { continue; } - const { url, isRequestable, layer, supports, media } = - resolvedAtRule; + const { url, requestable, layer, supports, media } = resolvedAtRule; - if (!isRequestable) { + if (!requestable) { options.api.push({ url, layer, supports, media, index }); // eslint-disable-next-line no-continue diff --git a/src/plugins/postcss-url-parser.js b/src/plugins/postcss-url-parser.js index c9b26525..27b61714 100644 --- a/src/plugins/postcss-url-parser.js +++ b/src/plugins/postcss-url-parser.js @@ -4,8 +4,7 @@ import { resolveRequests, normalizeUrl, requestify, - isUrlRequestable, - isDataUrl, + isURLRequestable, WEBPACK_IGNORE_COMMENT_REGEXP, } from "../utils"; @@ -48,30 +47,16 @@ function getWebpackIgnoreCommentValue(index, nodes, inBetween) { return matched && matched[2] === "true"; } -function shouldHandleURL(url, declaration, result, options = {}) { +function shouldHandleURL(url, declaration, result, options) { if (url.length === 0) { result.warn(`Unable to find uri in '${declaration.toString()}'`, { node: declaration, }); - return false; + return { requestable: false, needResolve: false }; } - if (isDataUrl(url) && options.isSupportDataURL) { - try { - decodeURIComponent(url); - } catch (ignoreError) { - return false; - } - - return true; - } - - if (!isUrlRequestable(url, options.isSupportAbsoluteURL)) { - return false; - } - - return true; + return isURLRequestable(url, options); } function parseDeclaration(declaration, key, result, options) { @@ -138,15 +123,24 @@ function parseDeclaration(declaration, key, result, options) { const { nodes } = valueNode; const isStringValue = nodes.length !== 0 && nodes[0].type === "string"; let url = isStringValue ? nodes[0].value : valueParser.stringify(nodes); + url = normalizeUrl(url, isStringValue); + const { requestable, needResolve } = shouldHandleURL( + url, + declaration, + result, + options + ); + // Do not traverse inside `url` - if (!shouldHandleURL(url, declaration, result, options)) { + if (!requestable) { // eslint-disable-next-line consistent-return return false; } const queryParts = url.split("!"); + let prefix; if (queryParts.length > 1) { @@ -161,6 +155,7 @@ function parseDeclaration(declaration, key, result, options) { prefix, url, needQuotes: false, + needResolve, }); // eslint-disable-next-line consistent-return @@ -194,15 +189,24 @@ function parseDeclaration(declaration, key, result, options) { let url = isStringValue ? nodes[0].value : valueParser.stringify(nodes); + url = normalizeUrl(url, isStringValue); + const { requestable, needResolve } = shouldHandleURL( + url, + declaration, + result, + options + ); + // Do not traverse inside `url` - if (!shouldHandleURL(url, declaration, result, options)) { + if (!requestable) { // eslint-disable-next-line consistent-return return false; } const queryParts = url.split("!"); + let prefix; if (queryParts.length > 1) { @@ -217,6 +221,7 @@ function parseDeclaration(declaration, key, result, options) { prefix, url, needQuotes: false, + needResolve, }); } else if (type === "string") { needIgnore = getWebpackIgnoreCommentValue( @@ -239,13 +244,21 @@ function parseDeclaration(declaration, key, result, options) { let url = normalizeUrl(value, true); + const { requestable, needResolve } = shouldHandleURL( + url, + declaration, + result, + options + ); + // Do not traverse inside `url` - if (!shouldHandleURL(url, declaration, result, options)) { + if (!requestable) { // eslint-disable-next-line consistent-return return false; } const queryParts = url.split("!"); + let prefix; if (queryParts.length > 1) { @@ -260,6 +273,7 @@ function parseDeclaration(declaration, key, result, options) { prefix, url, needQuotes: true, + needResolve, }); } } @@ -301,7 +315,7 @@ const plugin = (options = {}) => { const resolvedDeclarations = await Promise.all( parsedDeclarations.map(async (parsedDeclaration) => { - const { url } = parsedDeclaration; + const { url, needResolve } = parsedDeclaration; if (options.filter) { const needKeep = await options.filter(url); @@ -312,7 +326,7 @@ const plugin = (options = {}) => { } } - if (isDataUrl(url)) { + if (!needResolve) { // eslint-disable-next-line consistent-return return parsedDeclaration; } @@ -323,30 +337,31 @@ const plugin = (options = {}) => { let hash = query ? "?" : ""; hash += hashOrQuery ? `#${hashOrQuery}` : ""; - const { needToResolveURL, rootContext } = options; + const { resolver, rootContext } = options; const request = requestify( pathname, rootContext, - needToResolveURL + Boolean(resolver) ); - if (!needToResolveURL) { + if (!resolver) { // eslint-disable-next-line consistent-return return { ...parsedDeclaration, url: request, hash }; } - const { resolver, context } = options; - const resolvedUrl = await resolveRequests(resolver, context, [ - ...new Set([request, url]), - ]); + const resolvedURL = await resolveRequests( + resolver, + options.context, + [...new Set([request, url])] + ); - if (!resolvedUrl) { + if (!resolvedURL) { // eslint-disable-next-line consistent-return return; } // eslint-disable-next-line consistent-return - return { ...parsedDeclaration, url: resolvedUrl, hash }; + return { ...parsedDeclaration, url: resolvedURL, hash }; }) ); @@ -391,7 +406,7 @@ const plugin = (options = {}) => { options.imports.push({ type: "url", importName, - url: options.needToResolveURL + url: options.resolver ? options.urlHandler(newUrl) : JSON.stringify(newUrl), index, diff --git a/src/utils.js b/src/utils.js index fc94459d..c6b2b554 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1189,32 +1189,43 @@ async function resolveRequests(resolve, context, possibleRequests) { }); } -function isUrlRequestable(url, isSupportAbsoluteURL) { +function isURLRequestable(url, options = {}) { // Protocol-relative URLs if (/^\/\//.test(url)) { - return false; + return { requestable: false, needResolve: false }; + } + + // `#` URLs + if (/^#/.test(url)) { + return { requestable: false, needResolve: false }; + } + + // Data URI + if (isDataUrl(url) && options.isSupportDataURL) { + try { + decodeURIComponent(url); + } catch (ignoreError) { + return { requestable: false, needResolve: false }; + } + + return { requestable: true, needResolve: false }; } // `file:` protocol if (/^file:/i.test(url)) { - return true; + return { requestable: true, needResolve: true }; } // Absolute URLs if (/^[a-z][a-z0-9+.-]*:/i.test(url) && !NATIVE_WIN32_PATH.test(url)) { - if (isSupportAbsoluteURL) { - return true; + if (options.isSupportAbsoluteURL && /^https?:/i.test(url)) { + return { requestable: true, needResolve: false }; } - return false; + return { requestable: false, needResolve: false }; } - // `#` URLs - if (/^#/.test(url)) { - return false; - } - - return true; + return { requestable: true, needResolve: true }; } function sort(a, b) { @@ -1246,7 +1257,7 @@ export { getModuleCode, getExportCode, resolveRequests, - isUrlRequestable, + isURLRequestable, sort, WEBPACK_IGNORE_COMMENT_REGEXP, combineRequests, diff --git a/test/__snapshots__/import-option.test.js.snap b/test/__snapshots__/import-option.test.js.snap index a4470ab0..e6a85f8a 100644 --- a/test/__snapshots__/import-option.test.js.snap +++ b/test/__snapshots__/import-option.test.js.snap @@ -3166,6 +3166,43 @@ Warning ] `; +exports[`"import" option should work with absolute URLs: errors 1`] = `Array []`; + +exports[`"import" option should work with absolute URLs: module 1`] = ` +"// Imports +import ___CSS_LOADER_API_NO_SOURCEMAP_IMPORT___ from \\"../../../src/runtime/noSourceMaps.js\\"; +import ___CSS_LOADER_API_IMPORT___ from \\"../../../src/runtime/api.js\\"; +import ___CSS_LOADER_GET_URL_IMPORT___ from \\"../../../src/runtime/getUrl.js\\"; +var ___CSS_LOADER_URL_IMPORT_0___ = new URL(\\"https://raw.githubusercontent.com/webpack-contrib/css-loader/master/test/fixtures/url/img.png\\", import.meta.url); +var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_NO_SOURCEMAP_IMPORT___); +___CSS_LOADER_EXPORT___.push([module.id, \\"@import url(https://raw.githubusercontent.com/webpack-contrib/css-loader/master/test/fixtures/url/imported.css);\\"]); +var ___CSS_LOADER_URL_REPLACEMENT_0___ = ___CSS_LOADER_GET_URL_IMPORT___(___CSS_LOADER_URL_IMPORT_0___); +// Module +___CSS_LOADER_EXPORT___.push([module.id, \\"a {\\\\n background: url(\\" + ___CSS_LOADER_URL_REPLACEMENT_0___ + \\");\\\\n}\\\\n\\", \\"\\"]); +// Exports +export default ___CSS_LOADER_EXPORT___; +" +`; + +exports[`"import" option should work with absolute URLs: result 1`] = ` +Array [ + Array [ + "./import/absolute-url.css", + "@import url(https://raw.githubusercontent.com/webpack-contrib/css-loader/master/test/fixtures/url/imported.css);", + ], + Array [ + "./import/absolute-url.css", + "a { + background: url(replaced_file_protocol_/webpack/public/path/img.png); +} +", + "", + ], +] +`; + +exports[`"import" option should work with absolute URLs: warnings 1`] = `Array []`; + exports[`"import" option should work with circular \`@import\`: errors 1`] = `Array []`; exports[`"import" option should work with circular \`@import\`: module 1`] = ` @@ -3199,6 +3236,41 @@ a { exports[`"import" option should work with circular \`@import\`: warnings 1`] = `Array []`; +exports[`"import" option should work with data URI: errors 1`] = `Array []`; + +exports[`"import" option should work with data URI: module 1`] = ` +"// Imports +import ___CSS_LOADER_API_NO_SOURCEMAP_IMPORT___ from \\"../../../src/runtime/noSourceMaps.js\\"; +import ___CSS_LOADER_API_IMPORT___ from \\"../../../src/runtime/api.js\\"; +var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_NO_SOURCEMAP_IMPORT___); +___CSS_LOADER_EXPORT___.push([module.id, \\"@import url(data:text/css;charset=utf-8;base64,YSB7DQogIGNvbG9yOiByZWQ7DQp9);\\"]); +// Module +___CSS_LOADER_EXPORT___.push([module.id, \\"a {\\\\n display: block;\\\\n width: 100px;\\\\n}\\\\n\\", \\"\\"]); +// Exports +export default ___CSS_LOADER_EXPORT___; +" +`; + +exports[`"import" option should work with data URI: result 1`] = ` +Array [ + Array [ + "./import/data-uri.css", + "@import url(data:text/css;charset=utf-8;base64,YSB7DQogIGNvbG9yOiByZWQ7DQp9);", + ], + Array [ + "./import/data-uri.css", + "a { + display: block; + width: 100px; +} +", + "", + ], +] +`; + +exports[`"import" option should work with data URI: warnings 1`] = `Array []`; + exports[`"import" option should work with import.filter: errors 1`] = `Array []`; exports[`"import" option should work with import.filter: module 1`] = ` diff --git a/test/__snapshots__/url-option.test.js.snap b/test/__snapshots__/url-option.test.js.snap index 51bef66c..72b6257a 100644 --- a/test/__snapshots__/url-option.test.js.snap +++ b/test/__snapshots__/url-option.test.js.snap @@ -2547,7 +2547,6 @@ import ___CSS_LOADER_API_IMPORT___ from \\"../../../src/runtime/api.js\\"; import ___CSS_LOADER_GET_URL_IMPORT___ from \\"../../../src/runtime/getUrl.js\\"; var ___CSS_LOADER_URL_IMPORT_0___ = new URL(\\"https://raw.githubusercontent.com/webpack-contrib/css-loader/master/test/fixtures/url/img.png\\", import.meta.url); var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_NO_SOURCEMAP_IMPORT___); -___CSS_LOADER_EXPORT___.push([module.id, \\"@import url(https://raw.githubusercontent.com/webpack-contrib/css-loader/master/test/fixtures/url/imported.css);\\"]); var ___CSS_LOADER_URL_REPLACEMENT_0___ = ___CSS_LOADER_GET_URL_IMPORT___(___CSS_LOADER_URL_IMPORT_0___); // Module ___CSS_LOADER_EXPORT___.push([module.id, \\"a {\\\\n background: url(\\" + ___CSS_LOADER_URL_REPLACEMENT_0___ + \\");\\\\n}\\\\n\\", \\"\\"]); @@ -2558,10 +2557,6 @@ export default ___CSS_LOADER_EXPORT___; exports[`"url" option should work with absolute URLs: result 1`] = ` Array [ - Array [ - "./url/absolute-url.css", - "@import url(https://raw.githubusercontent.com/webpack-contrib/css-loader/master/test/fixtures/url/imported.css);", - ], Array [ "./url/absolute-url.css", "a { diff --git a/test/fixtures/import/absolute-url.css b/test/fixtures/import/absolute-url.css new file mode 100644 index 00000000..0d440b54 --- /dev/null +++ b/test/fixtures/import/absolute-url.css @@ -0,0 +1,5 @@ +@import url("https://raw.githubusercontent.com/webpack-contrib/css-loader/master/test/fixtures/url/imported.css"); + +a { + background: url("https://raw.githubusercontent.com/webpack-contrib/css-loader/master/test/fixtures/url/img.png"); +} diff --git a/test/fixtures/import/absolute-url.js b/test/fixtures/import/absolute-url.js new file mode 100644 index 00000000..738626eb --- /dev/null +++ b/test/fixtures/import/absolute-url.js @@ -0,0 +1,5 @@ +import css from './absolute-url.css'; + +__export__ = css; + +export default css; diff --git a/test/fixtures/import/data-uri.css b/test/fixtures/import/data-uri.css new file mode 100644 index 00000000..d4bb2b27 --- /dev/null +++ b/test/fixtures/import/data-uri.css @@ -0,0 +1,6 @@ +@import url("data:text/css;charset=utf-8;base64,YSB7DQogIGNvbG9yOiByZWQ7DQp9"); + +a { + display: block; + width: 100px; +} diff --git a/test/fixtures/import/data-uri.js b/test/fixtures/import/data-uri.js new file mode 100644 index 00000000..45baff5e --- /dev/null +++ b/test/fixtures/import/data-uri.js @@ -0,0 +1,5 @@ +import css from './data-uri.css'; + +__export__ = css; + +export default css; diff --git a/test/fixtures/url/absolute-url.css b/test/fixtures/url/absolute-url.css index 0d440b54..058c94b2 100644 --- a/test/fixtures/url/absolute-url.css +++ b/test/fixtures/url/absolute-url.css @@ -1,5 +1,3 @@ -@import url("https://raw.githubusercontent.com/webpack-contrib/css-loader/master/test/fixtures/url/imported.css"); - a { background: url("https://raw.githubusercontent.com/webpack-contrib/css-loader/master/test/fixtures/url/img.png"); } diff --git a/test/import-option.test.js b/test/import-option.test.js index d48076c3..7f403660 100644 --- a/test/import-option.test.js +++ b/test/import-option.test.js @@ -531,4 +531,47 @@ describe('"import" option', () => { expect(getWarnings(stats)).toMatchSnapshot("warnings"); expect(getErrors(stats)).toMatchSnapshot("errors"); }); + + it("should work with data URI", async () => { + const compiler = getCompiler("./import/data-uri.js"); + const stats = await compile(compiler); + + expect(getModuleSource("./import/data-uri.css", stats)).toMatchSnapshot( + "module" + ); + expect(getExecutedCode("main.bundle.js", compiler, stats)).toMatchSnapshot( + "result" + ); + expect(getWarnings(stats)).toMatchSnapshot("warnings"); + expect(getErrors(stats)).toMatchSnapshot("errors"); + }); + + it("should work with absolute URLs", async () => { + const compiler = getCompiler( + "./import/absolute-url.js", + {}, + { + experiments: { + buildHttp: { + allowedUris: [() => true], + lockfileLocation: path.resolve( + __dirname, + "./lock-files/import/lock.json" + ), + cacheLocation: path.resolve(__dirname, "./lock-files/import"), + }, + }, + } + ); + const stats = await compile(compiler); + + expect(getModuleSource("./import/absolute-url.css", stats)).toMatchSnapshot( + "module" + ); + expect(getExecutedCode("main.bundle.js", compiler, stats)).toMatchSnapshot( + "result" + ); + expect(getWarnings(stats)).toMatchSnapshot("warnings"); + expect(getErrors(stats)).toMatchSnapshot("errors"); + }); }); diff --git a/test/lock-files/https_raw.githubusercontent.com/webpack-contrib_css-loader_master_test_fixtures_url_img_fc0003ff99956138ca55.png b/test/lock-files/import/https_raw.githubusercontent.com/webpack-contrib_css-loader_master_test_fixtures_url_img_fc0003ff99956138ca55.png similarity index 100% rename from test/lock-files/https_raw.githubusercontent.com/webpack-contrib_css-loader_master_test_fixtures_url_img_fc0003ff99956138ca55.png rename to test/lock-files/import/https_raw.githubusercontent.com/webpack-contrib_css-loader_master_test_fixtures_url_img_fc0003ff99956138ca55.png diff --git a/test/lock-files/import/lock.json b/test/lock-files/import/lock.json new file mode 100644 index 00000000..aecaa7ed --- /dev/null +++ b/test/lock-files/import/lock.json @@ -0,0 +1,15 @@ +{ + "https://raw.githubusercontent.com/webpack-contrib/css-loader/master/test/fixtures/url/img-from-imported.png": { + "integrity": "sha512-bHqIPBYwzPsVLYcTDqJzwgvIaxLjmezufiCVXAMI0Naelf3eWVdydMA40hXbSuB0dZCGjCepuGaI7Ze8kLM+Ew==", + "contentType": "image/png" + }, + "https://raw.githubusercontent.com/webpack-contrib/css-loader/master/test/fixtures/url/img.png": { + "integrity": "sha512-bHqIPBYwzPsVLYcTDqJzwgvIaxLjmezufiCVXAMI0Naelf3eWVdydMA40hXbSuB0dZCGjCepuGaI7Ze8kLM+Ew==", + "contentType": "image/png" + }, + "https://raw.githubusercontent.com/webpack-contrib/css-loader/master/test/fixtures/url/imported.css": { + "integrity": "sha512-yduMovHFp1vmkdJda9uz9c3WIwPbmESRe9u1IrxoKKw0q3AjaMDyAwAuZqQW/HFi6fEdS+fAGkBI++JO6EeUSg==", + "contentType": "text/plain; charset=utf-8" + }, + "version": 1 +} diff --git a/test/lock-files/lock.json b/test/lock-files/lock.json deleted file mode 100644 index 7b0be466..00000000 --- a/test/lock-files/lock.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "https://raw.githubusercontent.com/webpack-contrib/css-loader/master/test/fixtures/url/img.png": { - "integrity": "sha512-bHqIPBYwzPsVLYcTDqJzwgvIaxLjmezufiCVXAMI0Naelf3eWVdydMA40hXbSuB0dZCGjCepuGaI7Ze8kLM+Ew==", - "contentType": "image/png" - }, - "version": 1 -} diff --git a/test/url-option.test.js b/test/url-option.test.js index a1f10bae..8868ff80 100644 --- a/test/url-option.test.js +++ b/test/url-option.test.js @@ -571,8 +571,11 @@ describe('"url" option', () => { experiments: { buildHttp: { allowedUris: [() => true], - lockfileLocation: path.resolve(__dirname, "./lock-files/lock.json"), - cacheLocation: path.resolve(__dirname, "./lock-files"), + lockfileLocation: path.resolve( + __dirname, + "./lock-files/url/lock.json" + ), + cacheLocation: path.resolve(__dirname, "./lock-files/url"), }, }, }