fix: css url public path
|
|
@ -5,7 +5,11 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const { ConcatSource, PrefixSource } = require("webpack-sources");
|
||||
const {
|
||||
ConcatSource,
|
||||
PrefixSource,
|
||||
ReplaceSource
|
||||
} = require("webpack-sources");
|
||||
const CssModule = require("../CssModule");
|
||||
const HotUpdateChunk = require("../HotUpdateChunk");
|
||||
const {
|
||||
|
|
@ -26,6 +30,7 @@ const StaticExportsDependency = require("../dependencies/StaticExportsDependency
|
|||
const { compareModulesByIdentifier } = require("../util/comparators");
|
||||
const createSchemaValidation = require("../util/create-schema-validation");
|
||||
const createHash = require("../util/createHash");
|
||||
const { getUndoPath } = require("../util/identifier");
|
||||
const memoize = require("../util/memoize");
|
||||
const nonNumericOnlyHash = require("../util/nonNumericOnlyHash");
|
||||
const CssExportsGenerator = require("./CssExportsGenerator");
|
||||
|
|
@ -356,6 +361,24 @@ class CssModulesPlugin {
|
|||
|
||||
/** @type {CssModule[] | undefined} */
|
||||
const modules = orderedCssModulesPerChunk.get(chunk);
|
||||
const { path: filename, info } = compilation.getPathWithInfo(
|
||||
CssModulesPlugin.getChunkFilenameTemplate(
|
||||
chunk,
|
||||
compilation.outputOptions
|
||||
),
|
||||
{
|
||||
hash,
|
||||
runtime: chunk.runtime,
|
||||
chunk,
|
||||
contentHashType: "css"
|
||||
}
|
||||
);
|
||||
const publicPath =
|
||||
compilation.outputOptions.publicPath === "auto"
|
||||
? getUndoPath(filename, compilation.outputOptions.path, false)
|
||||
: compilation.getAssetPath(compilation.outputOptions.publicPath, {
|
||||
hash: compilation.hash
|
||||
});
|
||||
if (modules !== undefined) {
|
||||
result.push({
|
||||
render: () =>
|
||||
|
|
@ -366,18 +389,11 @@ class CssModulesPlugin {
|
|||
uniqueName: compilation.outputOptions.uniqueName,
|
||||
cssHeadDataCompression:
|
||||
compilation.outputOptions.cssHeadDataCompression,
|
||||
publicPath,
|
||||
modules
|
||||
}),
|
||||
filenameTemplate: CssModulesPlugin.getChunkFilenameTemplate(
|
||||
chunk,
|
||||
compilation.outputOptions
|
||||
),
|
||||
pathOptions: {
|
||||
hash,
|
||||
runtime: chunk.runtime,
|
||||
chunk,
|
||||
contentHashType: "css"
|
||||
},
|
||||
filename,
|
||||
info,
|
||||
identifier: `css${chunk.id}`,
|
||||
hash: chunk.contentHash.css
|
||||
});
|
||||
|
|
@ -576,6 +592,7 @@ class CssModulesPlugin {
|
|||
* @param {Object} options options
|
||||
* @param {string | undefined} options.uniqueName unique name
|
||||
* @param {boolean | undefined} options.cssHeadDataCompression compress css head data
|
||||
* @param {string} options.publicPath public path
|
||||
* @param {Chunk} options.chunk chunk
|
||||
* @param {ChunkGraph} options.chunkGraph chunk graph
|
||||
* @param {CodeGenerationResults} options.codeGenerationResults code generation results
|
||||
|
|
@ -585,6 +602,7 @@ class CssModulesPlugin {
|
|||
renderChunk({
|
||||
uniqueName,
|
||||
cssHeadDataCompression,
|
||||
publicPath,
|
||||
chunk,
|
||||
chunkGraph,
|
||||
codeGenerationResults,
|
||||
|
|
@ -604,6 +622,24 @@ class CssModulesPlugin {
|
|||
codeGenResult.sources.get("css-import")
|
||||
);
|
||||
|
||||
let matches = [
|
||||
...moduleSource
|
||||
.source()
|
||||
.toString()
|
||||
.matchAll(new RegExp(CssUrlDependency.PUBLIC_PATH_PLACEHOLDER, "g"))
|
||||
];
|
||||
if (matches.length > 0) {
|
||||
const replaceSource = new ReplaceSource(moduleSource);
|
||||
for (const match of matches) {
|
||||
replaceSource.replace(
|
||||
match.index,
|
||||
(match.index += match[0].length - 1),
|
||||
publicPath
|
||||
);
|
||||
}
|
||||
moduleSource = replaceSource;
|
||||
}
|
||||
|
||||
let inheritance = [[module.cssLayer, module.supports, module.media]];
|
||||
|
||||
if (module.inheritance) {
|
||||
|
|
|
|||
|
|
@ -29,6 +29,8 @@ const getIgnoredRawDataUrlModule = memoize(() => {
|
|||
return new RawDataUrlModule("data:,", `ignored-asset`, `(ignored asset)`);
|
||||
});
|
||||
|
||||
const PUBLIC_PATH_PLACEHOLDER = "__CSS_URL_DEPENDENCY_PUBLIC_PATH__";
|
||||
|
||||
class CssUrlDependency extends ModuleDependency {
|
||||
/**
|
||||
* @param {string} request request
|
||||
|
|
@ -134,7 +136,7 @@ CssUrlDependency.Template = class CssUrlDependencyTemplate extends (
|
|||
case "string":
|
||||
newValue = cssEscapeString(
|
||||
runtimeTemplate.assetUrl({
|
||||
publicPath: "",
|
||||
publicPath: PUBLIC_PATH_PLACEHOLDER,
|
||||
module: /** @type {Module} */ (moduleGraph.getModule(dep)),
|
||||
codeGenerationResults
|
||||
})
|
||||
|
|
@ -143,7 +145,7 @@ CssUrlDependency.Template = class CssUrlDependencyTemplate extends (
|
|||
case "url":
|
||||
newValue = `url(${cssEscapeString(
|
||||
runtimeTemplate.assetUrl({
|
||||
publicPath: "",
|
||||
publicPath: PUBLIC_PATH_PLACEHOLDER,
|
||||
module: /** @type {Module} */ (moduleGraph.getModule(dep)),
|
||||
codeGenerationResults
|
||||
})
|
||||
|
|
@ -162,3 +164,4 @@ CssUrlDependency.Template = class CssUrlDependencyTemplate extends (
|
|||
makeSerializable(CssUrlDependency, "webpack/lib/dependencies/CssUrlDependency");
|
||||
|
||||
module.exports = CssUrlDependency;
|
||||
module.exports.PUBLIC_PATH_PLACEHOLDER = PUBLIC_PATH_PLACEHOLDER;
|
||||
|
|
|
|||
|
After Width: | Height: | Size: 76 KiB |
|
After Width: | Height: | Size: 76 KiB |
|
After Width: | Height: | Size: 76 KiB |
|
After Width: | Height: | Size: 76 KiB |
|
After Width: | Height: | Size: 76 KiB |
|
After Width: | Height: | Size: 76 KiB |
|
After Width: | Height: | Size: 76 KiB |
|
After Width: | Height: | Size: 76 KiB |
|
After Width: | Height: | Size: 76 KiB |
|
After Width: | Height: | Size: 76 KiB |
|
After Width: | Height: | Size: 76 KiB |
|
After Width: | Height: | Size: 76 KiB |
|
|
@ -0,0 +1,18 @@
|
|||
const testCase = (tagName, impFn) => {
|
||||
it(`should be able to handle styles in ${tagName}.css`, done => {
|
||||
const element = document.createElement(tagName);
|
||||
document.body.appendChild(element);
|
||||
impFn().then(x => {
|
||||
try {
|
||||
expect(x).toEqual(nsObj({}));
|
||||
const style = getComputedStyle(element);
|
||||
expect(style).toMatchSnapshot();
|
||||
done();
|
||||
} catch (e) {
|
||||
done(e);
|
||||
}
|
||||
}, done);
|
||||
});
|
||||
};
|
||||
|
||||
testCase("div", () => import("./spacing.css"));
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
@import url("#test");
|
||||
|
||||
.nested {
|
||||
background: url('./img.png');
|
||||
}
|
||||
|
After Width: | Height: | Size: 76 KiB |
|
After Width: | Height: | Size: 76 KiB |
|
After Width: | Height: | Size: 76 KiB |
BIN
test/configCases/css/urls-css-filename/node_modules/package/img.png
generated
vendored
Normal file
|
After Width: | Height: | Size: 76 KiB |
4
test/configCases/css/urls-css-filename/node_modules/package/package.json
generated
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"name": "package",
|
||||
"version": "1.0.0"
|
||||
}
|
||||
|
After Width: | Height: | Size: 76 KiB |
|
|
@ -0,0 +1,32 @@
|
|||
/** @type {import("../../../../").Configuration} */
|
||||
module.exports = {
|
||||
target: "web",
|
||||
mode: "development",
|
||||
devtool: false,
|
||||
experiments: {
|
||||
css: true
|
||||
},
|
||||
output: {
|
||||
cssFilename: "css/[name].css",
|
||||
cssChunkFilename: "css/async/[name].css",
|
||||
assetModuleFilename: "asset/[name].[hash][ext][query][fragment]"
|
||||
},
|
||||
optimization: {
|
||||
splitChunks: {
|
||||
cacheGroups: {
|
||||
assetFixHack: {
|
||||
type: "asset/resource",
|
||||
chunks: "all",
|
||||
name: "main",
|
||||
enforce: true
|
||||
},
|
||||
assetFixHack1: {
|
||||
type: "asset/inline",
|
||||
chunks: "all",
|
||||
name: "main",
|
||||
enforce: true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||