@lynx-js/css-extract-webpack-plugin 0.6.5 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # @lynx-js/css-extract-webpack-plugin
2
2
 
3
+ ## 0.7.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Fix CSS source map line offsets when wrapping extracted CSS with cssId metadata. ([#2514](https://github.com/lynx-family/lynx-stack/pull/2514))
8
+
9
+ - Support `@lynx-js/template-webpack-plugin` v0.11.0. ([#2483](https://github.com/lynx-family/lynx-stack/pull/2483))
10
+
11
+ ## 0.7.0
12
+
13
+ ### Minor Changes
14
+
15
+ - **BREAKING CHANGE**: Require `@lynx-js/template-webpack-plugin` 0.10.0. ([#1965](https://github.com/lynx-family/lynx-stack/pull/1965))
16
+
17
+ - Merge all css chunk and generate a `.css.hot-update.json` file for each bundle. ([#1965](https://github.com/lynx-family/lynx-stack/pull/1965))
18
+
3
19
  ## 0.6.5
4
20
 
5
21
  ### Patch Changes
@@ -23,7 +23,7 @@ interface CssExtractRspackPluginOptions extends ExternalCssExtractRspackPluginOp
23
23
  * @public
24
24
  *
25
25
  * CssExtractRspackPlugin is the CSS extract plugin for Lynx.
26
- * It works just like the {@link https://www.rspack.dev/plugins/rspack/css-extract-rspack-plugin.html | CssExtractRspackPlugin} in Web.
26
+ * It works just like the {@link https://rspack.rs/plugins/rspack/css-extract-rspack-plugin.html | CssExtractRspackPlugin} in Web.
27
27
  *
28
28
  * @example
29
29
  * ```js
@@ -8,7 +8,7 @@ const require = createRequire(import.meta.url);
8
8
  * @public
9
9
  *
10
10
  * CssExtractRspackPlugin is the CSS extract plugin for Lynx.
11
- * It works just like the {@link https://www.rspack.dev/plugins/rspack/css-extract-rspack-plugin.html | CssExtractRspackPlugin} in Web.
11
+ * It works just like the {@link https://rspack.rs/plugins/rspack/css-extract-rspack-plugin.html | CssExtractRspackPlugin} in Web.
12
12
  *
13
13
  * @example
14
14
  * ```js
@@ -95,6 +95,7 @@ class CssExtractRspackPluginImpl {
95
95
  this.options = options;
96
96
  this.name = 'CssExtractRspackPlugin';
97
97
  this.hash = null;
98
+ this.hotUpdateFiles = new Map();
98
99
  new compiler.webpack.CssExtractRspackPlugin({
99
100
  filename: options.filename ?? '[name].css',
100
101
  chunkFilename: options.chunkFilename ?? '',
@@ -110,9 +111,15 @@ class CssExtractRspackPluginImpl {
110
111
  // @ts-expect-error Rspack to Webpack Compilation
111
112
  compilation);
112
113
  hooks.beforeEmit.tapPromise(this.name, async (args) => {
113
- for (const { name: filename, source, } of args.cssChunks) {
114
- const content = source.source().toString('utf-8');
115
- const css = LynxTemplatePlugin.convertCSSChunksToMap([content], options.cssPlugins, Boolean(args.finalEncodeOptions.compilerOptions['enableCSSSelector']));
114
+ const cssChunks = args.cssChunks;
115
+ const content = cssChunks.map((chunk) => chunk.source.source().toString('utf-8'));
116
+ for (const entryName of args.entryNames) {
117
+ // generate hot update file which is required by cssHotUpdateList
118
+ const hotUpdateFilePath = this.hotUpdateFiles.get(entryName);
119
+ if (!hotUpdateFilePath) {
120
+ continue;
121
+ }
122
+ const css = LynxTemplatePlugin.convertCSSChunksToMap(content, options.cssPlugins, Boolean(args.finalEncodeOptions.compilerOptions['enableCSSSelector']));
116
123
  const cssDeps = Object.entries(css.cssMap).reduce((acc, [key, value]) => {
117
124
  const importRuleNodes = value.filter((node) => node.type === 'ImportRule');
118
125
  acc[key] = importRuleNodes.map(({ href }) => href);
@@ -140,7 +147,7 @@ class CssExtractRspackPluginImpl {
140
147
  content: buffer.toString('base64'),
141
148
  deps: cssDeps,
142
149
  };
143
- compilation.emitAsset(filename.replace('.css', `${this.hash ? `.${this.hash}` : ''}.css.hot-update.json`), new compiler.webpack.sources.RawSource(JSON.stringify(result), true));
150
+ compilation.emitAsset(hotUpdateFilePath, new compiler.webpack.sources.RawSource(JSON.stringify(result), true));
144
151
  }
145
152
  catch (error) {
146
153
  if (error && typeof error === 'object' && 'error_msg' in error) {
@@ -159,9 +166,10 @@ class CssExtractRspackPluginImpl {
159
166
  });
160
167
  const { RuntimeGlobals, RuntimeModule } = compiler.webpack;
161
168
  class CSSHotUpdateRuntimeModule extends RuntimeModule {
162
- constructor(hash) {
169
+ constructor(hash, hotUpdateFiles) {
163
170
  super('lynx css hot update');
164
171
  this.hash = hash;
172
+ this.hotUpdateFiles = hotUpdateFiles;
165
173
  }
166
174
  generate() {
167
175
  const chunk = this.chunk;
@@ -172,10 +180,16 @@ class CssExtractRspackPluginImpl {
172
180
  });
173
181
  const { path } = compilation.getPathWithInfo(options.filename ?? '[name].css', { chunk });
174
182
  const initialChunk = [chunk.name, path];
175
- const cssHotUpdateList = [...asyncChunks, initialChunk].map(([chunkName, cssHotUpdatePath]) => [
176
- chunkName,
177
- cssHotUpdatePath.replace('.css', `${this.hash ? `.${this.hash}` : ''}.css.hot-update.json`),
178
- ]);
183
+ const cssHotUpdateList = [...asyncChunks, initialChunk].map(([chunkName, cssHotUpdatePath]) => {
184
+ // use hash of previous compilation cause CSSHotUpdateRuntimeModule can not get hash immediately
185
+ const hotUpdatePath = cssHotUpdatePath.replace('.css', `${this.hash ? `.${this.hash}` : ''}.css.hot-update.json`);
186
+ // save all hot update file info
187
+ this.hotUpdateFiles.set(chunkName, hotUpdatePath);
188
+ return [
189
+ chunkName,
190
+ hotUpdatePath,
191
+ ];
192
+ });
179
193
  return `
180
194
  ${RuntimeGlobals.require}.cssHotUpdateList = ${cssHotUpdateList ? JSON.stringify(cssHotUpdateList) : 'null'};
181
195
  `;
@@ -187,7 +201,7 @@ ${RuntimeGlobals.require}.cssHotUpdateList = ${cssHotUpdateList ? JSON.stringify
187
201
  return;
188
202
  onceForChunkSet.add(chunk);
189
203
  runtimeRequirements.add(RuntimeGlobals.publicPath);
190
- compilation.addRuntimeModule(chunk, new CSSHotUpdateRuntimeModule(this.hash));
204
+ compilation.addRuntimeModule(chunk, new CSSHotUpdateRuntimeModule(this.hash, this.hotUpdateFiles));
191
205
  };
192
206
  compilation.hooks.runtimeRequirementInTree
193
207
  .for(RuntimeGlobals.ensureChunkHandlers)
package/lib/loader.d.ts CHANGED
@@ -32,6 +32,10 @@ export interface LoaderOptions {
32
32
  */
33
33
  layer?: string | undefined;
34
34
  }
35
+ interface DependencySourceMap {
36
+ mappings?: string | undefined;
37
+ [key: string]: unknown;
38
+ }
35
39
  export interface Dep {
36
40
  identifier: string;
37
41
  context: string | null;
@@ -43,5 +47,7 @@ export interface Dep {
43
47
  sourceMap?: Buffer | undefined;
44
48
  }
45
49
  export declare function load(this: LoaderContext<LoaderOptions>, request: string, addDependencies: (deps: Dep[]) => void): Promise<string>;
50
+ export declare function offsetSourceMapLines<T extends DependencySourceMap>(sourceMap: T, lineOffset: number): T;
46
51
  export declare function pitch(this: LoaderContext<LoaderOptions>, request: string): Promise<string | undefined>;
47
52
  export default function loader(this: LoaderContext<LoaderOptions>, content: string): string | undefined;
53
+ export {};
package/lib/loader.js CHANGED
@@ -54,13 +54,14 @@ export async function load(request, addDependencies) {
54
54
  params.set('cssId', cssId);
55
55
  }
56
56
  const filePath = path.relative(this.rootContext, extractPathFromIdentifier(identifier));
57
+ const shouldWrapCSSId = Boolean(cssId)
58
+ && (params.get('common') === null
59
+ || params.get('common') === 'false');
57
60
  identifierCountMap.set(identifier, count + 1);
58
61
  return {
59
62
  identifier: identifier.replace(rawResourcePath, `${resourcePath}?${params.toString()}`),
60
63
  context: this.rootContext,
61
- content: Buffer.from(cssId
62
- && (params.get('common') === null
63
- || params.get('common') === 'false')
64
+ content: Buffer.from(shouldWrapCSSId
64
65
  /**
65
66
  * Given the following source code:
66
67
  *
@@ -92,8 +93,7 @@ export async function load(request, addDependencies) {
92
93
  * }
93
94
  * ```
94
95
  */
95
- ? `\
96
- @cssId "${cssId}" "${filePath}" {
96
+ ? `@cssId "${cssId}" "${filePath}" {
97
97
  ${content}
98
98
  }
99
99
  `
@@ -103,7 +103,7 @@ ${content}
103
103
  layer,
104
104
  identifierIndex: count,
105
105
  sourceMap: sourceMap
106
- ? Buffer.from(JSON.stringify(sourceMap))
106
+ ? Buffer.from(JSON.stringify(shouldWrapCSSId ? offsetSourceMapLines(sourceMap, 1) : sourceMap))
107
107
  : undefined,
108
108
  };
109
109
  });
@@ -151,6 +151,15 @@ ${content}
151
151
  : result;
152
152
  return resultSource;
153
153
  }
154
+ export function offsetSourceMapLines(sourceMap, lineOffset) {
155
+ if (lineOffset <= 0 || !sourceMap.mappings) {
156
+ return sourceMap;
157
+ }
158
+ return {
159
+ ...sourceMap,
160
+ mappings: `${';'.repeat(lineOffset)}${sourceMap.mappings}`,
161
+ };
162
+ }
154
163
  export async function pitch(request) {
155
164
  if (this._compiler?.options?.experiments?.css
156
165
  && this._module
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lynx-js/css-extract-webpack-plugin",
3
- "version": "0.6.5",
3
+ "version": "0.7.1",
4
4
  "description": "This plugin extracts CSS into separate files. It creates a CSS file per JS file which contains CSS.",
5
5
  "keywords": [
6
6
  "webpack",
@@ -41,21 +41,21 @@
41
41
  "README.md"
42
42
  ],
43
43
  "dependencies": {
44
- "mini-css-extract-plugin": "^2.9.4"
44
+ "mini-css-extract-plugin": "^2.10.0"
45
45
  },
46
46
  "devDependencies": {
47
- "@microsoft/api-extractor": "7.52.15",
48
- "@rspack/core": "1.6.5",
49
- "css-loader": "^7.1.2",
50
- "sass-loader": "^16.0.5",
51
- "webpack": "^5.102.0",
52
- "@lynx-js/css-serializer": "0.1.3",
53
- "@lynx-js/template-webpack-plugin": "0.9.2",
47
+ "@microsoft/api-extractor": "7.58.2",
48
+ "@rspack/core": "1.7.9",
49
+ "css-loader": "^7.1.4",
50
+ "sass-loader": "^16.0.7",
51
+ "webpack": "^5.105.2",
52
+ "@lynx-js/css-serializer": "0.1.6",
53
+ "@lynx-js/template-webpack-plugin": "0.11.0",
54
54
  "@lynx-js/test-tools": "0.0.0",
55
55
  "@lynx-js/vitest-setup": "0.0.0"
56
56
  },
57
57
  "peerDependencies": {
58
- "@lynx-js/template-webpack-plugin": "^0.9.0"
58
+ "@lynx-js/template-webpack-plugin": "^0.11.0"
59
59
  },
60
60
  "engines": {
61
61
  "node": ">=18"