@next-core/build-next-bricks 1.3.1 → 1.4.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/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.1",
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": "4b4ee2a1f0853f0538ba78973cd10d76c5312027"
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
@@ -60,7 +60,6 @@ const getCssLoaders = (cssOptions) => [
60
60
  */
61
61
  async function getWebpackConfig(config) {
62
62
  const packageDir = process.cwd();
63
- // const isContainer = config.type === "container";
64
63
  const isBricks = !config.type || config.type === "bricks";
65
64
  const mode = config.mode || process.env.NODE_ENV;
66
65
 
@@ -126,7 +125,7 @@ async function getWebpackConfig(config) {
126
125
  }
127
126
  );
128
127
  } catch (e) {
129
- console.error(`Shared package not found: "${dep}"`);
128
+ console.warn(`Shared package not found: "${dep}"`);
130
129
  return;
131
130
  }
132
131
  const depPackageJsonFile = await readFile(depPackageJsonPath, {
@@ -159,29 +158,28 @@ async function getWebpackConfig(config) {
159
158
  /** @type {string[]} */
160
159
  const bricks = [];
161
160
  /** @type {string[]} */
161
+ const elements = [];
162
+ /** @type {string[]} */
162
163
  const processors = [];
163
164
  if (isBricks) {
164
- for (const key of Object.keys(config.exposes)) {
165
+ for (const [key, val] of Object.entries(config.exposes)) {
165
166
  const segments = key.split("/");
166
167
  const name = segments.pop();
167
168
  const namespace = segments.pop();
168
169
  if (namespace === "processors") {
169
170
  processors.push(`${camelPackageName}.${name}`);
170
171
  } else {
171
- bricks.push(`${packageName}.${name}`);
172
+ if (val[Symbol.for("noNamespace")]) {
173
+ elements.push(name);
174
+ } else {
175
+ bricks.push(`${packageName}.${name}`);
176
+ }
172
177
  }
173
178
  }
174
179
  }
175
180
 
176
181
  /** @type {Record<string, { import: string; name: string; }>} */
177
182
  const extraExposes = {};
178
- // const initializeTsPath = path.join(packageDir, "src/initialize.ts");
179
- // if (fs.existsSync(initializeTsPath)) {
180
- // extraExposes.initialize = {
181
- // import: `./${path.relative(packageDir, initializeTsPath)}`,
182
- // name: "initialize",
183
- // };
184
- // }
185
183
 
186
184
  const outputPath = path.join(packageDir, config.outputPath ?? "dist");
187
185
  const chunksDir = isBricks ? "chunks/" : "";
@@ -218,9 +216,6 @@ async function getWebpackConfig(config) {
218
216
  {
219
217
  test: /\.css$/,
220
218
  exclude: /\.(module|shadow|lazy)\.css$/,
221
- // resourceQuery: {
222
- // not: /shadow/
223
- // },
224
219
  sideEffects: true,
225
220
  use: [
226
221
  config.extractCss ? MiniCssExtractPlugin.loader : "style-loader",
@@ -235,15 +230,18 @@ async function getWebpackConfig(config) {
235
230
  }),
236
231
  ],
237
232
  },
238
- // {
239
- // test: /\.css$/,
240
- // resourceQuery: /shadow/,
241
- // use: [
242
- // ...getCssLoaders({
243
- // exportType: "string",
244
- // }),
245
- // ],
246
- // },
233
+ {
234
+ test: /\.module\.css$/,
235
+ sideEffects: true,
236
+ use: [
237
+ config.extractCss ? MiniCssExtractPlugin.loader : "style-loader",
238
+ ...getCssLoaders({
239
+ modules: {
240
+ localIdentName: "[local]--[hash:base64:8]",
241
+ },
242
+ }),
243
+ ],
244
+ },
247
245
  {
248
246
  test: /\.[tj]sx?$/,
249
247
  loader: "babel-loader",
@@ -296,12 +294,6 @@ async function getWebpackConfig(config) {
296
294
  ? {
297
295
  splitChunks: {
298
296
  cacheGroups: {
299
- react: {
300
- test: /[\\/]node_modules[\\/](?:react(?:-dom)?|scheduler)[\\/]/,
301
- priority: -10,
302
- reuseExistingChunk: true,
303
- name: "react",
304
- },
305
297
  default: {
306
298
  minChunks: 2,
307
299
  priority: -20,
@@ -369,6 +361,7 @@ async function getWebpackConfig(config) {
369
361
  new EmitBricksJsonPlugin({
370
362
  packageName,
371
363
  bricks,
364
+ elements,
372
365
  processors,
373
366
  dependencies: config.dependencies,
374
367
  }),
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"