piral-ng 1.12.3 → 1.12.4-beta.36dc2ff
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/README.md +33 -0
- package/angular-resource-loader.js +21 -0
- package/extend-rspack.js +143 -0
- package/package.json +5 -2
package/README.md
CHANGED
|
@@ -482,6 +482,39 @@ For AoT (i.e. `jitMode: false`) to work correctly the `compilationMode: 'partial
|
|
|
482
482
|
For AoT to work correctly the Angular sources need to be bundled. This is not the case in scenarios where you installed `piral-ng` as a plugin in your shell or distribute the Angular packages as shared dependencies from your app shell.
|
|
483
483
|
:::
|
|
484
484
|
|
|
485
|
+
Alternatively, if you want to use Rspack instead of Webpack you can use the convenience `extend-rspack` module.
|
|
486
|
+
|
|
487
|
+
This is how your *rspack.config.js* can look like:
|
|
488
|
+
|
|
489
|
+
```js
|
|
490
|
+
const extendRspack = require('piral-ng/extend-rspack');
|
|
491
|
+
|
|
492
|
+
module.exports = extendRspack();
|
|
493
|
+
```
|
|
494
|
+
|
|
495
|
+
For using `piral-ng/extend-rspack` you must have installed:
|
|
496
|
+
|
|
497
|
+
- `@rspack/core`
|
|
498
|
+
- `sass-loader` (only required if you use `.scss`/`.sass` component styles)
|
|
499
|
+
- `piral-cli-rspack`
|
|
500
|
+
|
|
501
|
+
You can do that via:
|
|
502
|
+
|
|
503
|
+
```sh
|
|
504
|
+
npm i @rspack/core sass-loader piral-cli-rspack --save-dev
|
|
505
|
+
```
|
|
506
|
+
|
|
507
|
+
The available options for `piral-ng/extend-rspack` are:
|
|
508
|
+
|
|
509
|
+
- `ngOptions` (currently only `jitMode`, which must stay at its default of `true`)
|
|
510
|
+
- `patterns` (providing input to the Rspack `CopyRspackPlugin`)
|
|
511
|
+
|
|
512
|
+
`piral-ng/extend-rspack` relies on Rspack's built-in CSS support (`css/auto`) for regular stylesheets, its built-in `asset/source` module type to inline component templates and component-scoped styles as raw strings, and its built-in `builtin:swc-loader` (configured for legacy decorators and decorator metadata) to compile TypeScript.
|
|
513
|
+
|
|
514
|
+
::: failure: AoT is not supported with Rspack
|
|
515
|
+
Angular's AoT compiler (`@ngtools/webpack`'s `AngularWebpackPlugin`) depends on Webpack-only compiler internals and does not work with Rspack. `piral-ng/extend-rspack` therefore only supports JIT builds (`jitMode: true`, the default) and throws if `jitMode: false` is requested. If you need an AoT production build with Rspack, use a dedicated Angular/Rspack builder such as [`@nx/angular-rspack`](https://www.npmjs.com/package/@nx/angular-rspack) instead.
|
|
516
|
+
:::
|
|
517
|
+
|
|
485
518
|
If you have set up the build process then you need to make sure that your application has an entry point (*index.ts*). That entry point has to be a valid pilet entry module. It may look as follows:
|
|
486
519
|
|
|
487
520
|
```ts
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// Rewrites `templateUrl`/`styleUrls`/`styleUrl` in `@Component()` metadata to inline
|
|
2
|
+
// `require()` calls, since Angular's JIT compiler needs the actual template/styles at
|
|
3
|
+
// class-decoration time - it does not fetch `templateUrl`/`styleUrls` over the network
|
|
4
|
+
// unless `resolveComponentResources()` was run, which we don't wire up here.
|
|
5
|
+
const templateUrlRegex = /templateUrl\s*:\s*(['"`])((?:\\.|(?!\1).)*)\1/g;
|
|
6
|
+
const styleUrlRegex = /styleUrl\s*:\s*(['"`])((?:\\.|(?!\1).)*)\1/g;
|
|
7
|
+
const styleUrlsRegex = /styleUrls\s*:\s*\[([^\]]*)\]/g;
|
|
8
|
+
const stringLiteralRegex = /(['"`])((?:\\.|(?!\1).)*)\1/g;
|
|
9
|
+
|
|
10
|
+
module.exports = function angularResourceLoader(source) {
|
|
11
|
+
source = source.replace(templateUrlRegex, (_, quote, url) => `template: require(${quote}${url}${quote})`);
|
|
12
|
+
|
|
13
|
+
source = source.replace(styleUrlRegex, (_, quote, url) => `styles: [require(${quote}${url}${quote})]`);
|
|
14
|
+
|
|
15
|
+
source = source.replace(styleUrlsRegex, (_, urls) => {
|
|
16
|
+
const requires = [...urls.matchAll(stringLiteralRegex)].map(([, quote, url]) => `require(${quote}${url}${quote})`);
|
|
17
|
+
return `styles: [${requires.join(', ')}]`;
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
return source;
|
|
21
|
+
};
|
package/extend-rspack.js
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
const { CopyRspackPlugin } = require('@rspack/core');
|
|
2
|
+
|
|
3
|
+
const { resolve } = require('path');
|
|
4
|
+
|
|
5
|
+
const sassLoader = require.resolve('sass-loader');
|
|
6
|
+
const angularResourceLoader = require.resolve('./angular-resource-loader');
|
|
7
|
+
|
|
8
|
+
module.exports =
|
|
9
|
+
(options = {}) =>
|
|
10
|
+
(config) => {
|
|
11
|
+
const {
|
|
12
|
+
patterns = [{ from: resolve(process.cwd(), 'src/assets'), noErrorOnMissing: true }],
|
|
13
|
+
ngOptions = {},
|
|
14
|
+
} = options;
|
|
15
|
+
const jitMode = ngOptions.jitMode ?? true;
|
|
16
|
+
|
|
17
|
+
if (!jitMode) {
|
|
18
|
+
// Angular AOT relies on @ngtools/webpack's AngularWebpackPlugin, which reaches into
|
|
19
|
+
// webpack-only compiler internals (e.g. resolverFactory) that Rspack does not provide.
|
|
20
|
+
// There is no drop-in AOT compiler for Rspack yet, so only JIT builds are supported here.
|
|
21
|
+
// For AOT with Rspack use a dedicated Angular/Rspack builder, e.g. `@nx/angular-rspack`.
|
|
22
|
+
throw new Error('piral-ng/extend-rspack only supports jitMode: true (AOT is not supported with Rspack).');
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// piral-cli-rspack nests all its rules in a single top-level `oneOf` array, with separate
|
|
26
|
+
// (non-merged) entries for `.ts` and `.tsx` - not a combined `/\.tsx?$/` pattern
|
|
27
|
+
const oneOf = config.module.rules.find((rule) => Array.isArray(rule.oneOf))?.oneOf;
|
|
28
|
+
|
|
29
|
+
if (!oneOf) {
|
|
30
|
+
throw new Error(
|
|
31
|
+
'piral-ng/extend-rspack could not find the expected module.rules[].oneOf array - is this an unsupported Rspack config?',
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
oneOf.forEach((rule) => {
|
|
36
|
+
const test = rule.test?.toString();
|
|
37
|
+
|
|
38
|
+
// exclude component-scoped styles from the regular (global) stylesheet handling,
|
|
39
|
+
// they are inlined into the component as raw text below instead
|
|
40
|
+
if (test === /\.css$/i.toString()) {
|
|
41
|
+
rule.exclude = /\.component.css$/i;
|
|
42
|
+
} else if (test === /\.s[ac]ss$/i.toString()) {
|
|
43
|
+
rule.exclude = /\.component.s[ac]ss$/i;
|
|
44
|
+
} else if (test === /\.ts$/.toString() || test === /\.tsx$/.toString()) {
|
|
45
|
+
// Angular's JIT mode only needs TypeScript's decorator/metadata transform - no
|
|
46
|
+
// Angular-specific compiler is required, so Rspack's native SWC loader handles it
|
|
47
|
+
delete rule.loader;
|
|
48
|
+
delete rule.options;
|
|
49
|
+
rule.use = [
|
|
50
|
+
{
|
|
51
|
+
loader: 'builtin:swc-loader',
|
|
52
|
+
options: {
|
|
53
|
+
jsc: {
|
|
54
|
+
parser: {
|
|
55
|
+
syntax: 'typescript',
|
|
56
|
+
tsx: test === /\.tsx$/.toString(),
|
|
57
|
+
decorators: true,
|
|
58
|
+
// Angular puts decorators before `export`, e.g. `@Component() export class`
|
|
59
|
+
decoratorsBeforeExport: true,
|
|
60
|
+
},
|
|
61
|
+
transform: {
|
|
62
|
+
legacyDecorator: true,
|
|
63
|
+
decoratorMetadata: true,
|
|
64
|
+
useDefineForClassFields: false,
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
// loaders run right-to-left, so this rewrites templateUrl/styleUrls to require()
|
|
70
|
+
// calls before the SWC loader compiles the result
|
|
71
|
+
angularResourceLoader,
|
|
72
|
+
];
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
// Angular templates/styles are consumed as plain strings - Rspack's built-in asset/source
|
|
77
|
+
// type exports the raw content without any loader; unshifted so it runs before the catch-all rule
|
|
78
|
+
oneOf.unshift(
|
|
79
|
+
{
|
|
80
|
+
test: /\.component.html$/i,
|
|
81
|
+
type: 'asset/source',
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
test: /\.component.css$/i,
|
|
85
|
+
type: 'asset/source',
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
// sass-loader compiles to CSS first, asset/source then exports the result as a string
|
|
89
|
+
test: /\.component.s[ac]ss$/i,
|
|
90
|
+
use: [sassLoader],
|
|
91
|
+
type: 'asset/source',
|
|
92
|
+
},
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
// The job of this plugin is
|
|
96
|
+
// (1)
|
|
97
|
+
// to make @angular/core depend on @angular/compiler - this way @angular/compiler
|
|
98
|
+
// does not need to be loaded separately and @angular/compiler is present *before*
|
|
99
|
+
// @angular/core; this is only required in jit mode - as otherwise everything should
|
|
100
|
+
// be pre-compiled.
|
|
101
|
+
// (2)
|
|
102
|
+
// to introduce a dynamic version of the window.ng global, which supports running
|
|
103
|
+
// with multiple versions of Angular.
|
|
104
|
+
config.plugins.push({
|
|
105
|
+
apply(compiler) {
|
|
106
|
+
const { entry } = compiler.options;
|
|
107
|
+
const coreEntry = entry['angular-core'];
|
|
108
|
+
const compilerEntry = entry['angular-compiler'];
|
|
109
|
+
|
|
110
|
+
if (typeof coreEntry !== 'undefined') {
|
|
111
|
+
const compilerDependency = resolve(__dirname, 'core-dynamic.js');
|
|
112
|
+
coreEntry.import = [compilerDependency, ...coreEntry.import];
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (typeof compilerEntry !== 'undefined') {
|
|
116
|
+
const compilerDependency = resolve(__dirname, 'compiler-dynamic.js');
|
|
117
|
+
compilerEntry.import = [compilerDependency, ...compilerEntry.import];
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// if @angular/core / @angular/compiler aren't split into their own shared-dependency
|
|
121
|
+
// entries (e.g. a plain pilet build), make sure @angular/compiler still loads before
|
|
122
|
+
// any Angular code runs - otherwise JIT compilation fails at runtime
|
|
123
|
+
if (typeof coreEntry === 'undefined' && typeof compilerEntry === 'undefined') {
|
|
124
|
+
const compilerDependency = resolve(__dirname, 'core-dynamic.js');
|
|
125
|
+
|
|
126
|
+
Object.values(entry).forEach((e) => {
|
|
127
|
+
if (e && Array.isArray(e.import)) {
|
|
128
|
+
e.import = [compilerDependency, ...e.import];
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
},
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
config.plugins.push(
|
|
136
|
+
new CopyRspackPlugin({
|
|
137
|
+
patterns,
|
|
138
|
+
}),
|
|
139
|
+
);
|
|
140
|
+
|
|
141
|
+
return config;
|
|
142
|
+
};
|
|
143
|
+
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "piral-ng",
|
|
3
|
-
"version": "1.12.
|
|
3
|
+
"version": "1.12.4-beta.36dc2ff",
|
|
4
4
|
"description": "Plugin for integrating Angular components in Piral.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"piral",
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
"./compiler-dynamic": "./compiler-dynamic.js",
|
|
26
26
|
"./convert": "./convert.js",
|
|
27
27
|
"./core-dynamic": "./core-dynamic.js",
|
|
28
|
+
"./extend-rspack": "./extend-rspack.js",
|
|
28
29
|
"./extend-webpack": "./extend-webpack.js",
|
|
29
30
|
"./standalone": "./lib/standalone.js",
|
|
30
31
|
"./lib/*": {
|
|
@@ -37,12 +38,14 @@
|
|
|
37
38
|
"files": [
|
|
38
39
|
"lib",
|
|
39
40
|
"src",
|
|
41
|
+
"angular-resource-loader.js",
|
|
40
42
|
"common.d.ts",
|
|
41
43
|
"common.js",
|
|
42
44
|
"compiler-dynamic.js",
|
|
43
45
|
"convert.d.ts",
|
|
44
46
|
"convert.js",
|
|
45
47
|
"core-dynamic.js",
|
|
48
|
+
"extend-rspack.js",
|
|
46
49
|
"extend-webpack.js"
|
|
47
50
|
],
|
|
48
51
|
"repository": {
|
|
@@ -71,7 +74,7 @@
|
|
|
71
74
|
"@angular/platform-browser": "^16.0.0",
|
|
72
75
|
"@angular/platform-browser-dynamic": "^16.0.0",
|
|
73
76
|
"@angular/router": "^16.0.0",
|
|
74
|
-
"piral-core": "^1.12.
|
|
77
|
+
"piral-core": "^1.12.4-beta.36dc2ff",
|
|
75
78
|
"piral-ng-common": "^16.0.0",
|
|
76
79
|
"rxjs": "^7.3.0"
|
|
77
80
|
}
|