Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support absolute URL, when experiments.buildHttp enabled #1389

Merged
merged 2 commits into from
Oct 26, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3,978 changes: 2,069 additions & 1,909 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -63,7 +63,7 @@
"del": "^6.0.0",
"del-cli": "^4.0.1",
"es-check": "^6.0.0",
"eslint": "^7.30.0",
"eslint": "^8.1.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-import": "^2.23.4",
"file-loader": "^6.2.0",
20 changes: 17 additions & 3 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -54,9 +54,24 @@ export default async function loader(content, map, meta) {
const importPluginImports = [];
const importPluginApi = [];

let isSupportAbsoluteURL = false;

// TODO enable by default in the next major release
if (
this._compilation &&
this._compilation.options &&
this._compilation.options.experiments &&
this._compilation.options.experiments.buildHttp
) {
isSupportAbsoluteURL = true;
}
const isSupportDataURL =
options.esModule && Boolean("fsStartTime" in this._compiler);

if (shouldUseImportPlugin(options)) {
plugins.push(
importParser({
isSupportAbsoluteURL,
isCSSStyleSheet: options.exportType === "css-style-sheet",
loaderContext: this,
imports: importPluginImports,
@@ -75,11 +90,11 @@ export default async function loader(content, map, meta) {

if (shouldUseURLPlugin(options)) {
const needToResolveURL = !options.esModule;
const isSupportDataURLInNewURL =
options.esModule && Boolean("fsStartTime" in this._compiler);

plugins.push(
urlParser({
isSupportAbsoluteURL,
isSupportDataURL,
imports: urlPluginImports,
replacements,
context: this.context,
@@ -92,7 +107,6 @@ export default async function loader(content, map, meta) {
undefined,
urlHandler: (url) => stringifyRequest(this, url),
// Support data urls as input in new URL added in webpack@5.38.0
isSupportDataURLInNewURL,
})
);
}
32 changes: 12 additions & 20 deletions src/plugins/postcss-url-parser.js
Original file line number Diff line number Diff line change
@@ -48,7 +48,7 @@ function getWebpackIgnoreCommentValue(index, nodes, inBetween) {
return matched && matched[2] === "true";
}

function shouldHandleURL(url, declaration, result, isSupportDataURLInNewURL) {
function shouldHandleURL(url, declaration, result, options = {}) {
if (url.length === 0) {
result.warn(`Unable to find uri in '${declaration.toString()}'`, {
node: declaration,
@@ -57,7 +57,7 @@ function shouldHandleURL(url, declaration, result, isSupportDataURLInNewURL) {
return false;
}

if (isDataUrl(url) && isSupportDataURLInNewURL) {
if (isDataUrl(url) && options.isSupportDataURL) {
try {
decodeURIComponent(url);
} catch (ignoreError) {
@@ -67,14 +67,14 @@ function shouldHandleURL(url, declaration, result, isSupportDataURLInNewURL) {
return true;
}

if (!isUrlRequestable(url)) {
if (!isUrlRequestable(url, options.isSupportAbsoluteURL)) {
return false;
}

return true;
}

function parseDeclaration(declaration, key, result, isSupportDataURLInNewURL) {
function parseDeclaration(declaration, key, result, options) {
if (!needParseDeclaration.test(declaration[key])) {
return;
}
@@ -141,9 +141,7 @@ function parseDeclaration(declaration, key, result, isSupportDataURLInNewURL) {
url = normalizeUrl(url, isStringValue);

// Do not traverse inside `url`
if (
!shouldHandleURL(url, declaration, result, isSupportDataURLInNewURL)
) {
if (!shouldHandleURL(url, declaration, result, options)) {
// eslint-disable-next-line consistent-return
return false;
}
@@ -199,9 +197,7 @@ function parseDeclaration(declaration, key, result, isSupportDataURLInNewURL) {
url = normalizeUrl(url, isStringValue);

// Do not traverse inside `url`
if (
!shouldHandleURL(url, declaration, result, isSupportDataURLInNewURL)
) {
if (!shouldHandleURL(url, declaration, result, options)) {
// eslint-disable-next-line consistent-return
return false;
}
@@ -244,9 +240,7 @@ function parseDeclaration(declaration, key, result, isSupportDataURLInNewURL) {
let url = normalizeUrl(value, true);

// Do not traverse inside `url`
if (
!shouldHandleURL(url, declaration, result, isSupportDataURLInNewURL)
) {
if (!shouldHandleURL(url, declaration, result, options)) {
// eslint-disable-next-line consistent-return
return false;
}
@@ -288,13 +282,11 @@ const plugin = (options = {}) => {

return {
Declaration(declaration) {
const { isSupportDataURLInNewURL } = options;
const parsedURL = parseDeclaration(
declaration,
"value",
result,
isSupportDataURLInNewURL
);
const { isSupportDataURL, isSupportAbsoluteURL } = options;
const parsedURL = parseDeclaration(declaration, "value", result, {
isSupportDataURL,
isSupportAbsoluteURL,
});

if (!parsedURL) {
return;
8 changes: 4 additions & 4 deletions src/runtime/api.js
Original file line number Diff line number Diff line change
@@ -51,17 +51,17 @@ module.exports = (cssWithMappingToString) => {
const alreadyImportedModules = {};

if (dedupe) {
for (let i = 0; i < this.length; i++) {
const id = this[i][0];
for (let k = 0; k < this.length; k++) {
const id = this[k][0];

if (id != null) {
alreadyImportedModules[id] = true;
}
}
}

for (let i = 0; i < modules.length; i++) {
const item = [].concat(modules[i]);
for (let k = 0; k < modules.length; k++) {
const item = [].concat(modules[k]);

if (dedupe && alreadyImportedModules[item[0]]) {
continue;
6 changes: 5 additions & 1 deletion src/utils.js
Original file line number Diff line number Diff line change
@@ -1189,7 +1189,7 @@ async function resolveRequests(resolve, context, possibleRequests) {
});
}

function isUrlRequestable(url) {
function isUrlRequestable(url, isSupportAbsoluteURL) {
// Protocol-relative URLs
if (/^\/\//.test(url)) {
return false;
@@ -1202,6 +1202,10 @@ function isUrlRequestable(url) {

// Absolute URLs
if (/^[a-z][a-z0-9+.-]*:/i.test(url) && !NATIVE_WIN32_PATH.test(url)) {
if (isSupportAbsoluteURL) {
return true;
}

return false;
}

37 changes: 37 additions & 0 deletions test/__snapshots__/url-option.test.js.snap
Original file line number Diff line number Diff line change
@@ -2538,6 +2538,43 @@ Warning
]
`;

exports[`"url" option should work with absolute URLs: errors 1`] = `Array []`;

exports[`"url" 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[`"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 {
background: url(replaced_file_protocol_/webpack/public/path/img.png);
}
",
"",
],
]
`;

exports[`"url" option should work with absolute URLs: warnings 1`] = `Array []`;

exports[`"url" option should work with mini-css-extract-plugin: css 1`] = `
"/*!*****************************************************************************!*\\\\
!*** css ../../src/index.js??ruleSet[1].rules[0].use[1]!./url/imported.css ***!
5 changes: 5 additions & 0 deletions test/fixtures/url/absolute-url.css
Original file line number Diff line number Diff line change
@@ -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");
}
5 changes: 5 additions & 0 deletions test/fixtures/url/absolute-url.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import css from './absolute-url.css';

__export__ = css;

export default css;
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 7 additions & 0 deletions test/lock-files/lock.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"https://raw.githubusercontent.com/webpack-contrib/css-loader/master/test/fixtures/url/img.png": {
"integrity": "sha512-bHqIPBYwzPsVLYcTDqJzwgvIaxLjmezufiCVXAMI0Naelf3eWVdydMA40hXbSuB0dZCGjCepuGaI7Ze8kLM+Ew==",
"contentType": "image/png"
},
"version": 1
}
2 changes: 1 addition & 1 deletion test/sourceMap-option.test.js
Original file line number Diff line number Diff line change
@@ -498,7 +498,7 @@ describe('"sourceMap" option', () => {
(assetName) => /\.js$/.test(assetName)
);

expect(chunkName).toBe("main.043d33a99a1aeaa533ff.bundle.js");
expect(chunkName).toBe("main.25338c5bc4249008fa47.bundle.js");
expect(
getModuleSource("fixtures/source-map/basic.css", stats)
).toMatchSnapshot("module");
26 changes: 26 additions & 0 deletions test/url-option.test.js
Original file line number Diff line number Diff line change
@@ -562,4 +562,30 @@ describe('"url" option', () => {
expect(getWarnings(stats)).toMatchSnapshot("warnings");
expect(getErrors(stats)).toMatchSnapshot("errors");
});

it("should work with absolute URLs", async () => {
const compiler = getCompiler(
"./url/absolute-url.js",
{},
{
experiments: {
buildHttp: {
allowedUris: [() => true],
lockfileLocation: path.resolve(__dirname, "./lock-files/lock.json"),
cacheLocation: path.resolve(__dirname, "./lock-files"),
},
},
}
);
const stats = await compile(compiler);

expect(getModuleSource("./url/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");
});
});