From f33eab015b47f6db590b5a3b27e8102d6d56c942 Mon Sep 17 00:00:00 2001 From: "alexander.akait" Date: Wed, 22 May 2024 17:21:51 +0300 Subject: [PATCH] fix: keep order of `@import`s with the `webpackIgnore` comment --- src/plugins/postcss-import-parser.js | 33 ++++++++++++----- test/__snapshots__/import-option.test.js.snap | 36 +++++++++++++++++++ test/fixtures/import/webpackIgnore-order.css | 7 ++++ test/fixtures/import/webpackIgnore-order.js | 5 +++ test/import-option.test.js | 14 ++++++++ 5 files changed, 86 insertions(+), 9 deletions(-) create mode 100644 test/fixtures/import/webpackIgnore-order.css create mode 100644 test/fixtures/import/webpackIgnore-order.js diff --git a/src/plugins/postcss-import-parser.js b/src/plugins/postcss-import-parser.js index 9a9de03d..142e105f 100644 --- a/src/plugins/postcss-import-parser.js +++ b/src/plugins/postcss-import-parser.js @@ -8,12 +8,7 @@ import { WEBPACK_IGNORE_COMMENT_REGEXP, } from "../utils"; -function parseNode(atRule, key, options) { - // Convert only top-level @import - if (atRule.parent.type !== "root") { - return; - } - +function isIgnoredAfterName(atRule) { if ( atRule.raws && atRule.raws.afterName && @@ -25,20 +20,35 @@ function parseNode(atRule, key, options) { .match(WEBPACK_IGNORE_COMMENT_REGEXP); if (matched && matched[2] === "true") { - return; + return true; } } + return false; +} + +function isIgnoredPrevNode(atRule) { const prevNode = atRule.prev(); if (prevNode && prevNode.type === "comment") { const matched = prevNode.text.match(WEBPACK_IGNORE_COMMENT_REGEXP); if (matched && matched[2] === "true") { - return; + return true; } } + return false; +} + +function parseNode(atRule, key, options) { + // Convert only top-level @import + if (atRule.parent.type !== "root") { + return; + } + + const isIgnored = isIgnoredAfterName(atRule) || isIgnoredPrevNode(atRule); + // Nodes do not exists - `@import url('http://') :root {}` if (atRule.nodes) { const error = new Error( @@ -97,7 +107,12 @@ function parseNode(atRule, key, options) { url = normalizeUrl(url, isStringValue); - const { requestable, needResolve } = isURLRequestable(url, options); + let requestable = false; + let needResolve = false; + + if (!isIgnored) { + ({ requestable, needResolve } = isURLRequestable(url, options)); + } let prefix; diff --git a/test/__snapshots__/import-option.test.js.snap b/test/__snapshots__/import-option.test.js.snap index 09cf8312..f0aa2ca8 100644 --- a/test/__snapshots__/import-option.test.js.snap +++ b/test/__snapshots__/import-option.test.js.snap @@ -1,5 +1,41 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`"import" option should jeep order of imports with 'webpackIgnore': errors 1`] = `[]`; + +exports[`"import" option should jeep order of imports with 'webpackIgnore': 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_AT_RULE_IMPORT_0___ from "-!../../../src/index.js??ruleSet[1].rules[0].use[0]!./test.css"; +var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_NO_SOURCEMAP_IMPORT___); +___CSS_LOADER_EXPORT___.push([module.id, "@import url(/assets/themes.css);"]); +___CSS_LOADER_EXPORT___.i(___CSS_LOADER_AT_RULE_IMPORT_0___); +// Module +___CSS_LOADER_EXPORT___.push([module.id, \`/*! /* webpackIgnore: true */ + +body { + background: red; +} +\`, ""]); +// Exports +export default ___CSS_LOADER_EXPORT___; +" +`; + +exports[`"import" option should jeep order of imports with 'webpackIgnore': result 1`] = ` +"@import url(/assets/themes.css);.test { + a: a; +} +/*! /* webpackIgnore: true */ + +body { + background: red; +} +" +`; + +exports[`"import" option should jeep order of imports with 'webpackIgnore': warnings 1`] = `[]`; + exports[`"import" option should keep original order: errors 1`] = `[]`; exports[`"import" option should keep original order: module 1`] = ` diff --git a/test/fixtures/import/webpackIgnore-order.css b/test/fixtures/import/webpackIgnore-order.css new file mode 100644 index 00000000..c0c6b1fd --- /dev/null +++ b/test/fixtures/import/webpackIgnore-order.css @@ -0,0 +1,7 @@ +/*! /* webpackIgnore: true */ +@import url("/assets/themes.css"); +@import "~test"; + +body { + background: red; +} diff --git a/test/fixtures/import/webpackIgnore-order.js b/test/fixtures/import/webpackIgnore-order.js new file mode 100644 index 00000000..f5a9e72e --- /dev/null +++ b/test/fixtures/import/webpackIgnore-order.js @@ -0,0 +1,5 @@ +import css from './webpackIgnore-order.css'; + +__export__ = css.toString(); + +export default css; diff --git a/test/import-option.test.js b/test/import-option.test.js index 36413154..dda2268e 100644 --- a/test/import-option.test.js +++ b/test/import-option.test.js @@ -588,4 +588,18 @@ describe('"import" option', () => { expect(getWarnings(stats)).toMatchSnapshot("warnings"); expect(getErrors(stats)).toMatchSnapshot("errors"); }); + + it("should jeep order of imports with 'webpackIgnore'", async () => { + const compiler = getCompiler("./import/webpackIgnore-order.js"); + const stats = await compile(compiler); + + expect( + getModuleSource("./import/webpackIgnore-order.css", stats), + ).toMatchSnapshot("module"); + expect(getExecutedCode("main.bundle.js", compiler, stats)).toMatchSnapshot( + "result", + ); + expect(getWarnings(stats)).toMatchSnapshot("warnings"); + expect(getErrors(stats)).toMatchSnapshot("errors"); + }); });