@lynx-js/react-webpack-plugin 0.7.4 → 0.9.0

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,35 @@
1
1
  # @lynx-js/react-webpack-plugin
2
2
 
3
+ ## 0.9.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Add `removeCall` for shake function calls. Its initial default value matches the hooks that were previously in `removeCallParams`, and `removeCallParams` now defaults to empty. ([#2423](https://github.com/lynx-family/lynx-stack/pull/2423))
8
+
9
+ `removeCall` removes matched runtime hook calls entirely, replacing them with `undefined` in expression positions and dropping them in statement positions. `removeCallParams` keeps the existing behavior of preserving the call while stripping its arguments.
10
+
11
+ ## 0.8.0
12
+
13
+ ### Minor Changes
14
+
15
+ - feat: add `globalPropsMode` option to `PluginReactLynxOptions` ([#2346](https://github.com/lynx-family/lynx-stack/pull/2346))
16
+
17
+ - When configured to `"event"`, `updateGlobalProps` will only trigger a global event and skip the `runWithForce` flow.
18
+ - Defaults to `"reactive"`, which means `updateGlobalProps` will trigger re-render automatically.
19
+
20
+ ### Patch Changes
21
+
22
+ - Fix sourcemap misalignment when wrapping lazy bundle main-thread chunks. ([#2361](https://github.com/lynx-family/lynx-stack/pull/2361))
23
+
24
+ The lazy bundle IIFE wrapper is now injected in `processAssets` at `PROCESS_ASSETS_STAGE_OPTIMIZE_SIZE + 1` by walking chunk groups instead of patching assets in `beforeEncode`.
25
+
26
+ - With `experimental_isLazyBundle: true`, the wrapper is applied to lazy-bundle chunk groups.
27
+ - Without lazy bundle mode, the wrapper is applied to async main-thread chunk groups generated by dynamic import.
28
+
29
+ Injecting the wrapper in this stage keeps the emitted JS stable after optimization while still running before `DEV_TOOLING` sourcemap finalization, so the generated `.js` and `.js.map` stay aligned.
30
+
31
+ - Set `__DEV__` and `__PROFILE__` to `true` on `NODE_ENV === 'development'`. ([#2324](https://github.com/lynx-family/lynx-stack/pull/2324))
32
+
3
33
  ## 0.7.4
4
34
 
5
35
  ### Patch Changes
@@ -15,6 +15,10 @@ interface ReactWebpackPluginOptions {
15
15
  * {@inheritdoc @lynx-js/react-rsbuild-plugin#PluginReactLynxOptions.firstScreenSyncTiming}
16
16
  */
17
17
  firstScreenSyncTiming?: 'immediately' | 'jsReady';
18
+ /**
19
+ * {@inheritdoc @lynx-js/react-rsbuild-plugin#PluginReactLynxOptions.globalPropsMode}
20
+ */
21
+ globalPropsMode?: 'reactive' | 'event';
18
22
  /**
19
23
  * {@inheritdoc @lynx-js/react-rsbuild-plugin#PluginReactLynxOptions.enableSSR}
20
24
  */
@@ -73,6 +73,7 @@ class ReactWebpackPlugin {
73
73
  .freeze({
74
74
  disableCreateSelectorQueryIncompatibleWarning: false,
75
75
  firstScreenSyncTiming: 'immediately',
76
+ globalPropsMode: 'reactive',
76
77
  enableSSR: false,
77
78
  mainThreadChunks: [],
78
79
  extractStr: false,
@@ -100,19 +101,22 @@ class ReactWebpackPlugin {
100
101
  // Use undefined for variables that must be provided during bundling, or null if they are optional.
101
102
  DEBUG: null,
102
103
  }).apply(compiler);
104
+ const isDev = process.env['NODE_ENV'] === 'development'
105
+ || compiler.options.mode === 'development';
103
106
  new DefinePlugin({
104
- __DEV__: JSON.stringify(compiler.options.mode === 'development'),
107
+ __DEV__: isDev,
105
108
  // We enable profile by default in development.
106
109
  // It can also be disabled by environment variable `REACT_PROFILE=false`
107
110
  __PROFILE__: JSON.stringify(process.env['REACT_PROFILE']
108
111
  ?? options.profile
109
- ?? compiler.options.mode === 'development'),
112
+ ?? isDev),
110
113
  // User can enable ALog by environment variable `REACT_ALOG=true`
111
114
  __ALOG__: JSON.stringify(Boolean(process.env['REACT_ALOG'])),
112
115
  // User can enable ALog of element API calls by environment variable `REACT_ALOG_ELEMENT_API=true`
113
116
  __ALOG_ELEMENT_API__: JSON.stringify(Boolean(process.env['REACT_ALOG_ELEMENT_API'])),
114
117
  __EXTRACT_STR__: JSON.stringify(Boolean(options.extractStr)),
115
118
  __FIRST_SCREEN_SYNC_TIMING__: JSON.stringify(options.firstScreenSyncTiming),
119
+ __GLOBAL_PROPS_MODE__: JSON.stringify(options.globalPropsMode),
116
120
  __ENABLE_SSR__: JSON.stringify(options.enableSSR),
117
121
  __DISABLE_CREATE_SELECTOR_QUERY_INCOMPATIBLE_WARNING__: JSON.stringify(options.disableCreateSelectorQueryIncompatibleWarning),
118
122
  }).apply(compiler);
@@ -168,26 +172,50 @@ class ReactWebpackPlugin {
168
172
  }
169
173
  return args;
170
174
  });
171
- // Inject `module.exports` for async main-thread chunks
172
- hooks.beforeEncode.tap(this.constructor.name, (args) => {
173
- const { encodeData } = args;
174
- // A lazy bundle may not have main-thread code
175
- if (!encodeData.lepusCode.root) {
176
- return args;
177
- }
178
- if (encodeData.sourceContent.appType === 'card') {
179
- return args;
180
- }
181
- // We inject `module.exports` for each async template.
182
- compilation.updateAsset(encodeData.lepusCode.root.name, (old) => new ConcatSource(`\
183
- (function (globDynamicComponentEntry) {
184
- const module = { exports: {} }
185
- const exports = module.exports;
186
- `, old, `
187
- ;return module.exports
188
- })`));
189
- return args;
190
- });
175
+ if (compiler.options.plugins.some((p) => p instanceof LynxTemplatePlugin)) {
176
+ compilation.hooks.processAssets.tap({
177
+ name: this.constructor.name,
178
+ // This wrapper must be injected after size/minify optimizations have
179
+ // produced stable JS, but before devtool plugins finalize sourcemaps and
180
+ // later encode hooks consume the wrapped asset.
181
+ //
182
+ // - Too early (<= OPTIMIZE_SIZE): the wrapper is added before the
183
+ // minimizer runs. For lazy bundles, the minimizer can treat the wrapped
184
+ // content as removable and collapse the emitted asset down to empty code.
185
+ // - Too late (>= DEV_TOOLING): SourceMapDevToolPlugin emits `.map` assets
186
+ // and rewrites JS with `sourceMappingURL` in DEV_TOOLING. If we prepend
187
+ // wrapper lines after that point, the generated JS shifts but mappings do
188
+ // not.
189
+ //
190
+ // OPTIMIZE_SIZE + 1 is the safe window where both the emitted code and its
191
+ // sourcemap stay aligned.
192
+ stage: compiler.webpack.Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE_SIZE
193
+ + 1,
194
+ }, () => {
195
+ compilation.chunkGroups.forEach(chunkGroup => {
196
+ const isDynamicImport = !chunkGroup.isInitial()
197
+ && chunkGroup.origins.every(origin => origin.module?.layer === LAYERS.MAIN_THREAD);
198
+ chunkGroup.chunks.forEach(chunk => {
199
+ for (const file of chunk.files) {
200
+ if (!file.endsWith('.js')) {
201
+ continue;
202
+ }
203
+ const shouldInjectWrapper = isDynamicImport
204
+ || (options.experimental_isLazyBundle
205
+ && options.mainThreadChunks?.includes(file));
206
+ if (!shouldInjectWrapper) {
207
+ continue;
208
+ }
209
+ const asset = compilation.getAsset(file);
210
+ if (!asset) {
211
+ continue;
212
+ }
213
+ compilation.updateAsset(file, old => new ConcatSource(`(function (globDynamicComponentEntry) {\n`, ` const module = { exports: {} }\n`, ` const exports = module.exports;\n`, old, `\n ;return module.exports\n})`));
214
+ }
215
+ });
216
+ });
217
+ });
218
+ }
191
219
  // The react-transform will add `-react__${LAYER}` to the webpackChunkName.
192
220
  // We replace it with an empty string here to make sure main-thread & background chunk match.
193
221
  hooks.asyncChunkName.tap(this.constructor.name, (chunkName) => chunkName
@@ -135,6 +135,8 @@ export function getMainThreadTransformOptions(inputSourceMap) {
135
135
  // so never pass true to shake to rust
136
136
  pkgName: [
137
137
  'react',
138
+ 'preact/hooks',
139
+ 'preact/compat',
138
140
  PUBLIC_RUNTIME_PKG,
139
141
  `${PUBLIC_RUNTIME_PKG}/legacy-react-runtime`,
140
142
  RUNTIME_PKG,
@@ -154,14 +156,15 @@ export function getMainThreadTransformOptions(inputSourceMap) {
154
156
  'defaultProps',
155
157
  ...(shake?.retainProp ?? []),
156
158
  ],
157
- removeCallParams: [
159
+ removeCall: [
158
160
  'useEffect',
159
161
  'useLayoutEffect',
160
162
  '__runInJS',
161
163
  'useLynxGlobalEventListener',
162
164
  'useImperativeHandle',
163
- ...(shake?.removeCallParams ?? []),
165
+ ...(shake?.removeCall ?? []),
164
166
  ],
167
+ removeCallParams: shake?.removeCallParams ?? [],
165
168
  },
166
169
  worklet: {
167
170
  ...commonOptions.worklet,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lynx-js/react-webpack-plugin",
3
- "version": "0.7.4",
3
+ "version": "0.9.0",
4
4
  "description": "A webpack plugin for ReactLynx",
5
5
  "keywords": [
6
6
  "webpack",
@@ -37,15 +37,15 @@
37
37
  "@lynx-js/webpack-runtime-globals": "0.0.6"
38
38
  },
39
39
  "devDependencies": {
40
- "@microsoft/api-extractor": "7.56.3",
41
- "@rspack/core": "1.7.6",
40
+ "@microsoft/api-extractor": "7.58.2",
41
+ "@rspack/core": "1.7.9",
42
42
  "css-loader": "^7.1.4",
43
43
  "swc-loader": "^0.2.7",
44
44
  "webpack": "^5.105.2",
45
45
  "@lynx-js/css-extract-webpack-plugin": "0.7.0",
46
- "@lynx-js/react": "0.116.3",
47
- "@lynx-js/template-webpack-plugin": "0.10.3",
46
+ "@lynx-js/react": "0.118.0",
48
47
  "@lynx-js/test-tools": "0.0.0",
48
+ "@lynx-js/template-webpack-plugin": "0.10.8",
49
49
  "@lynx-js/vitest-setup": "0.0.0"
50
50
  },
51
51
  "peerDependencies": {