@next-core/build-next-bricks 1.3.1 → 1.4.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/index.d.ts CHANGED
@@ -81,7 +81,9 @@ export interface BuildNextBricksConfig {
81
81
  imageAssetFilename?: string | ((pathData: any, assetInfo: any) => string);
82
82
  plugins?: Configuration["plugins"];
83
83
  moduleRules?: RuleSetRule[];
84
- exposes?: ConstructorParameters<typeof container.ModuleFederationPlugin>;
84
+ exposes?: ConstructorParameters<
85
+ typeof container.ModuleFederationPlugin
86
+ >[0]["exposes"];
85
87
  dependencies?: Record<string, string[]>;
86
88
  optimization?: Configuration["optimization"];
87
89
  moduleFederationShared?: SharedObject | false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@next-core/build-next-bricks",
3
- "version": "1.3.1",
3
+ "version": "1.4.0",
4
4
  "description": "Build next bricks",
5
5
  "homepage": "https://github.com/easyops-cn/next-core/tree/master/packages/build-next-bricks",
6
6
  "license": "GPL-3.0",
@@ -46,5 +46,5 @@
46
46
  "typescript": "^5.0.3",
47
47
  "webpack": "^5.78.0"
48
48
  },
49
- "gitHead": "9e99998974ba369577d5ff6c01cd2aefb451a432"
49
+ "gitHead": "ea57221d8b3ba0c15ea0ec6c583865c4dce2fb5f"
50
50
  }
@@ -9,6 +9,7 @@ export default class EmitBricksJsonPlugin {
9
9
  constructor(options) {
10
10
  this.packageName = options.packageName;
11
11
  this.bricks = options.bricks;
12
+ this.elements = options.elements;
12
13
  this.processors = options.processors;
13
14
  this.dependencies = options.dependencies;
14
15
  }
@@ -45,6 +46,7 @@ export default class EmitBricksJsonPlugin {
45
46
  {
46
47
  id: `bricks/${this.packageName}`,
47
48
  bricks: this.bricks,
49
+ elements: this.elements,
48
50
  processors: this.processors,
49
51
  dependencies: this.dependencies,
50
52
  filePath: jsFilePath,
@@ -59,6 +61,7 @@ export default class EmitBricksJsonPlugin {
59
61
  );
60
62
 
61
63
  console.log("Defined bricks:", this.bricks);
64
+ console.log("Defined elements:", this.elements);
62
65
  console.log("Defined processors:", this.processors);
63
66
  console.log("Found dependencies:", this.dependencies);
64
67
  callback();
package/src/build.js CHANGED
@@ -159,16 +159,22 @@ async function getWebpackConfig(config) {
159
159
  /** @type {string[]} */
160
160
  const bricks = [];
161
161
  /** @type {string[]} */
162
+ const elements = [];
163
+ /** @type {string[]} */
162
164
  const processors = [];
163
165
  if (isBricks) {
164
- for (const key of Object.keys(config.exposes)) {
166
+ for (const [key, val] of Object.entries(config.exposes)) {
165
167
  const segments = key.split("/");
166
168
  const name = segments.pop();
167
169
  const namespace = segments.pop();
168
170
  if (namespace === "processors") {
169
171
  processors.push(`${camelPackageName}.${name}`);
170
172
  } else {
171
- bricks.push(`${packageName}.${name}`);
173
+ if (val[Symbol.for("noNamespace")]) {
174
+ elements.push(name);
175
+ } else {
176
+ bricks.push(`${packageName}.${name}`);
177
+ }
172
178
  }
173
179
  }
174
180
  }
@@ -218,9 +224,6 @@ async function getWebpackConfig(config) {
218
224
  {
219
225
  test: /\.css$/,
220
226
  exclude: /\.(module|shadow|lazy)\.css$/,
221
- // resourceQuery: {
222
- // not: /shadow/
223
- // },
224
227
  sideEffects: true,
225
228
  use: [
226
229
  config.extractCss ? MiniCssExtractPlugin.loader : "style-loader",
@@ -235,15 +238,18 @@ async function getWebpackConfig(config) {
235
238
  }),
236
239
  ],
237
240
  },
238
- // {
239
- // test: /\.css$/,
240
- // resourceQuery: /shadow/,
241
- // use: [
242
- // ...getCssLoaders({
243
- // exportType: "string",
244
- // }),
245
- // ],
246
- // },
241
+ {
242
+ test: /\.module\.css$/,
243
+ sideEffects: true,
244
+ use: [
245
+ config.extractCss ? MiniCssExtractPlugin.loader : "style-loader",
246
+ ...getCssLoaders({
247
+ modules: {
248
+ localIdentName: "[local]--[hash:base64:8]",
249
+ },
250
+ }),
251
+ ],
252
+ },
247
253
  {
248
254
  test: /\.[tj]sx?$/,
249
255
  loader: "babel-loader",
@@ -369,6 +375,7 @@ async function getWebpackConfig(config) {
369
375
  new EmitBricksJsonPlugin({
370
376
  packageName,
371
377
  bricks,
378
+ elements,
372
379
  processors,
373
380
  dependencies: config.dependencies,
374
381
  }),
package/src/scanBricks.js CHANGED
@@ -11,6 +11,7 @@ const { escapeRegExp } = _;
11
11
 
12
12
  const validBrickName =
13
13
  /^[a-z][a-z0-9]*(-[a-z0-9]+)*\.[a-z][a-z0-9]*(-[a-z0-9]+)+$/;
14
+ const validCustomElementName = /^[a-z][a-z0-9]*(-[a-z0-9]+)+$/;
14
15
  const validProcessorName = /^[a-z][a-zA-Z0-9]*\.[a-z][a-zA-Z0-9]*$/;
15
16
  const validExposeName = /^[-\w]+$/;
16
17
 
@@ -18,7 +19,7 @@ const validExposeName = /^[-\w]+$/;
18
19
  * Scan defined bricks by AST.
19
20
  *
20
21
  * @param {string} packageDir
21
- * @returns {Promise<{exposes: Record<string, { import: string; name: string; }; dependencies: Record<string, string[]>}>>}
22
+ * @returns {Promise<{exposes: Record<string, { import: string; name: string; noNamespace?: boolean; }; dependencies: Record<string, string[]>}>>}
22
23
  */
23
24
  export default async function scanBricks(packageDir) {
24
25
  /** @type {Map<string, { import: string; name: string; }>} */
@@ -85,6 +86,18 @@ export default async function scanBricks(packageDir) {
85
86
  let nextOverrideImport = overrideImport;
86
87
  if (content.startsWith("// Merge bricks")) {
87
88
  nextOverrideImport = filePath;
89
+ } else if (content.startsWith("// Define brick")) {
90
+ // Match any source files starting with specific comments:
91
+ // `// Define brick: sl-alert` or
92
+ // `// Define bricks: sl-alert, sl-icon`
93
+ const firstLine = content.split("\n", 1)[0];
94
+ const match = firstLine.match(/^\/\/ Define bricks?: (.+)$/);
95
+ if (match) {
96
+ const bricks = match[1].split(/,\s*/g);
97
+ for (const brick of bricks) {
98
+ collectBrick(brick);
99
+ }
100
+ }
88
101
  }
89
102
 
90
103
  /**
@@ -123,6 +136,57 @@ export default async function scanBricks(packageDir) {
123
136
  }
124
137
  }
125
138
 
139
+ /**
140
+ * @param {string} fullName
141
+ */
142
+ function collectBrick(fullName) {
143
+ /** @type string */
144
+ let brickNamespace;
145
+ /** @type string */
146
+ let brickName;
147
+ let noNamespace = false;
148
+ if (fullName.includes(".")) {
149
+ [brickNamespace, brickName] = fullName.split(".");
150
+ if (brickNamespace !== packageName) {
151
+ throw new Error(
152
+ `Invalid brick: "${fullName}", expecting prefixed with the package name: "${packageName}"`
153
+ );
154
+ }
155
+
156
+ if (!validBrickName.test(fullName)) {
157
+ throw new Error(
158
+ `Invalid brick: "${fullName}", expecting: "PACKAGE-NAME.BRICK-NAME", where PACKAGE-NAME and BRICK-NAME must be lower-kebab-case, and BRICK-NAME must include a \`-\``
159
+ );
160
+ }
161
+
162
+ if (brickName.startsWith("tpl-")) {
163
+ throw new Error(
164
+ `Invalid brick: "${fullName}", the brick name cannot be started with "tpl-"`
165
+ );
166
+ }
167
+ } else {
168
+ // For third-party custom elements, there maybe no namespace.
169
+ brickName = fullName;
170
+ noNamespace = true;
171
+ if (!validCustomElementName.test(brickName)) {
172
+ throw new Error(
173
+ `Invalid brick: "${fullName}", the brick name must include a \`-\``
174
+ );
175
+ }
176
+ }
177
+
178
+ brickSourceFiles.set(fullName, filePath);
179
+
180
+ exposes.set(`./${brickName}`, {
181
+ import: `./${path
182
+ .relative(packageDir, overrideImport || filePath)
183
+ .replace(/\.[^.]+$/, "")
184
+ .replace(/\/index$/, "")}`,
185
+ name: getExposeName(brickName),
186
+ [Symbol.for("noNamespace")]: noNamespace,
187
+ });
188
+ }
189
+
126
190
  traverse(ast, {
127
191
  CallExpression({ node: { callee, arguments: args } }) {
128
192
  // Match `customProcessors.define(...)`
@@ -172,34 +236,7 @@ export default async function scanBricks(packageDir) {
172
236
  ) {
173
237
  const { type, value: fullName } = args[0];
174
238
  if (type === "StringLiteral") {
175
- const [brickNamespace, brickName] = fullName.split(".");
176
- if (brickNamespace !== packageName) {
177
- throw new Error(
178
- `Invalid brick: "${fullName}", expecting prefixed with the package name: "${packageName}"`
179
- );
180
- }
181
-
182
- if (!validBrickName.test(fullName)) {
183
- throw new Error(
184
- `Invalid brick: "${fullName}", expecting: "PACKAGE-NAME.BRICK-NAME", where PACKAGE-NAME and BRICK-NAME must be lower-kebab-case, and BRICK-NAME must include a \`-\``
185
- );
186
- }
187
-
188
- if (brickName.startsWith("tpl-")) {
189
- throw new Error(
190
- `Invalid brick: "${fullName}", the brick name cannot be started with "tpl-"`
191
- );
192
- }
193
-
194
- brickSourceFiles.set(fullName, filePath);
195
-
196
- exposes.set(`./${brickName}`, {
197
- import: `./${path
198
- .relative(packageDir, overrideImport || filePath)
199
- .replace(/\.[^.]+$/, "")
200
- .replace(/\/index$/, "")}`,
201
- name: getExposeName(brickName),
202
- });
239
+ collectBrick(fullName);
203
240
  } else {
204
241
  throw new Error(
205
242
  "Please call `customElements.define()` only with literal string"