@imtf/profile-scripts 1.5.3 → 2.0.0-beta.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/README.md ADDED
@@ -0,0 +1,275 @@
1
+ # @imtf/profile-scripts (Vite + Module Federation)
2
+
3
+ ## Overview
4
+
5
+ `profile-scripts` is a standardized build and development utility designed for Profile applications within the ICOS.
6
+
7
+ It provides a **vite-based build** with optional **Module Federation integration**.
8
+
9
+ ---
10
+
11
+ ## Installation
12
+
13
+ ```bash
14
+ npm install --save-dev @imtf/profile-scripts
15
+ ```
16
+
17
+ or
18
+
19
+ ```bash
20
+ yarn add -D @imtf/profile-scripts
21
+ ```
22
+
23
+ ---
24
+
25
+ ## Usage
26
+
27
+ ### Start (development/watch mode)
28
+
29
+ ```bash
30
+ profile-scripts start
31
+ ```
32
+
33
+ Starts the build in watch mode and serves output at:
34
+
35
+ ```
36
+ http://localhost:3010
37
+ ```
38
+
39
+ ---
40
+
41
+ ### Build (Production)
42
+
43
+ ```bash
44
+ profile-scripts build
45
+ ```
46
+
47
+ Generates the production bundle in the `build/` directory.
48
+
49
+ ---
50
+
51
+ ## CLI Options
52
+
53
+ ### `--entryPoint`
54
+
55
+ Specify a custom entry file.
56
+
57
+ ```bash
58
+ profile-scripts start --entryPoint src/index.ts
59
+ ```
60
+
61
+ If not provided, the following files are checked (in order):
62
+
63
+ ```
64
+ index.ts
65
+ index.tsx
66
+ index.js
67
+ index.jsx
68
+ src/index.ts
69
+ src/index.tsx
70
+ src/index.js
71
+ src/index.jsx
72
+ ```
73
+
74
+ ---
75
+
76
+ ### `--federation`
77
+
78
+ Enable Module Federation support.
79
+
80
+ ```bash
81
+ profile-scripts start --federation
82
+ ```
83
+
84
+ When enabled:
85
+ - Loads configuration from `federation.config.js` or `federation.config.mjs` in project root
86
+ - Integrates with `vite-plugin-federation`
87
+
88
+ ---
89
+
90
+ ### `--externalGlobal`
91
+
92
+ Map external dependencies to global variables (optional).
93
+
94
+ ```bash
95
+ profile-scripts build --externalGlobal=react/jsx-runtime=window.jsxRuntime
96
+ ```
97
+
98
+ Use this when a dependency is provided globally by the host application and should not be bundled.
99
+
100
+ ---
101
+
102
+ ## Project Requirements
103
+
104
+ Minimal structure:
105
+
106
+ ```
107
+ project-root/
108
+ src/
109
+ index.tsx (or equivalent entry)
110
+ package.json
111
+ ```
112
+
113
+ For Module Federation:
114
+
115
+ ```
116
+ federation.config.js
117
+ ```
118
+
119
+ ---
120
+
121
+ ## Remote Application Requirements
122
+
123
+ To enable Module Federation integration, the **remote application** must be configured as follows.
124
+
125
+ ### Module Federation Configuration
126
+
127
+ ```js
128
+ module.exports = {
129
+ name: "remote-app",
130
+ exposes: {
131
+ "./App": "./src/App",
132
+ },
133
+ filename: "remoteEntry.js",
134
+ library: { type: "module" }, // **required**
135
+ };
136
+ ```
137
+
138
+ ---
139
+
140
+ ### Build Configuration
141
+
142
+ ```js
143
+ experiments: { outputModule: true },
144
+
145
+ externalsType: "global",
146
+
147
+ externals: {
148
+ react: "React",
149
+ "react-dom": "ReactDOM",
150
+ };
151
+ ```
152
+
153
+ ### Notes
154
+
155
+ * The `library.type = "module"` configuration is **mandatory** for compatibility with vite-based host applications
156
+ * `outputModule: true` ensures the remote is emitted as an ES module
157
+ * React dependencies must be externalised and provided by the host application
158
+
159
+ ---
160
+
161
+ ## SVG Handling
162
+
163
+ Built-in SVG support:
164
+
165
+ - Files inside `src/` → transformed into React components
166
+ - Files inside `src/assets/` or outside `src/` → converted to base64 data URLs
167
+
168
+ ---
169
+
170
+ ## CSS Handling
171
+
172
+ CSS is automatically injected into the JavaScript bundle.
173
+ No separate CSS files are generated.
174
+
175
+ ---
176
+
177
+ ## Output
178
+
179
+ Build output:
180
+
181
+ ```
182
+ build/
183
+ index.js
184
+ ```
185
+
186
+ - Format: IIFE
187
+ - Designed for integration into host applications
188
+
189
+ ---
190
+
191
+ ## Environment Variable
192
+
193
+ ### `IMTF_MINIFY_WEBAPP`
194
+
195
+ Controls minification:
196
+
197
+ ```bash
198
+ IMTF_MINIFY_WEBAPP=false profile-scripts build
199
+ ```
200
+
201
+ - Default: minification enabled
202
+ - Uses Vite default minifier
203
+
204
+ ---
205
+
206
+ ## Notes
207
+
208
+ - vite is the default build system
209
+ - Module Federation is enabled only via `--federation`
210
+ - Entry point is optional but must resolve to a valid file
211
+ - External globals should be used only when dependencies are provided by the host
212
+
213
+ ---
214
+ ## Profile Configuration
215
+ Two supported approaches are available based on how the remote is resolved.
216
+
217
+ ---
218
+
219
+ ### Option 1: URL-based Remote (Static)
220
+
221
+ ```js
222
+ export default {
223
+ name: "host-app",
224
+ remotes: {
225
+ remoteModule: {
226
+ externalType: "url",
227
+ external: "http://localhost:3021/remoteEntry.js",
228
+ from: "webpack",
229
+ format: "esm",
230
+ },
231
+ },
232
+ };
233
+ ```
234
+
235
+ ---
236
+
237
+ ### Option 2: Promise-based Remote (Dynamic)
238
+
239
+ Use this when the remote URL needs to be resolved dynamically at runtime.
240
+
241
+ ```js
242
+ export default {
243
+ name: "host-app",
244
+ remotes: {
245
+ remoteapp: {
246
+ externalType: "promise",
247
+ external: "<<resolver function as string>>",
248
+ from: "webpack",
249
+ format: "esm",
250
+ },
251
+ },
252
+ };
253
+ ```
254
+
255
+ ---
256
+
257
+ ## Troubleshooting
258
+
259
+ ### Entry point not found
260
+
261
+ Ensure one of the supported entry files exists or pass `--entryPoint`.
262
+
263
+ ---
264
+
265
+ ### Federation configuration missing
266
+
267
+ Ensure `federation.config.js` or `.mjs` exists when using `--federation`.
268
+
269
+ ---
270
+
271
+ ### Runtime dependency issues
272
+
273
+ If a dependency is expected from the host, configure it using `--externalGlobal`.
274
+
275
+ ---
@@ -7,7 +7,7 @@ const args = process.argv.slice(2);
7
7
  const scriptIndex = args.findIndex((x) => x === "build" || x === "start");
8
8
  const script = scriptIndex === -1 ? args[0] : args[scriptIndex];
9
9
 
10
- const scriptPath = require.resolve(`../scripts/esbuild.mjs`);
10
+ const scriptPath = require.resolve("../scripts/viteBuild.mjs");
11
11
 
12
12
  switch (script) {
13
13
  case "start":
package/changelog.md CHANGED
@@ -2,6 +2,14 @@
2
2
 
3
3
  Here you can find a resume of all changes between versions.
4
4
 
5
+ ## 2.0.0
6
+
7
+ ### Breaking changes
8
+
9
+ - ViteJS will now be used as the default bundler for development and production builds.
10
+ The previous version of the package used esbuild.
11
+ This change allows Module Federation to be supported.
12
+
5
13
  ## 1.5.0
6
14
 
7
15
  ### Features
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@imtf/profile-scripts",
3
- "version": "1.5.3",
3
+ "version": "2.0.0-beta.1",
4
4
  "description": "Default scripts to bundle & transpile imtf front-end plugins",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -12,21 +12,23 @@
12
12
  "changelog.md"
13
13
  ],
14
14
  "scripts": {
15
- "build": "NODE_ENV=production node scripts/esbuild.mjs --entryPoint=src/index.tsx",
16
- "start": "node scripts/esbuild.mjs --entryPoint=src/index.tsx --watch"
15
+ "build": "NODE_ENV=production node scripts/viteBuild.mjs",
16
+ "start": "node scripts/viteBuild.mjs --watch"
17
17
  },
18
18
  "prettier": "@imtf/prettier-config",
19
19
  "license": "UNLICENSED",
20
20
  "private": false,
21
21
  "dependencies": {
22
- "@svgr/core": "^8.1.0",
23
- "@svgr/plugin-jsx": "^8.1.0",
24
- "@svgr/plugin-svgo": "^8.1.0",
22
+ "@originjs/vite-plugin-federation": "^1.4.1",
23
+ "@vitejs/plugin-react": "^5.1.4",
25
24
  "esbuild": "^0.27.0",
26
- "esbuild-css-modules-plugin": "^3.1.4",
27
- "esbuild-plugin-external-global": "^1.0.1",
28
- "esbuild-plugin-inline-css": "^0.0.1",
29
- "http-server": "^14.1.1",
30
- "minimist": "^1.2.8"
25
+ "minimist": "^1.2.8",
26
+ "serve-handler": "^6.1.6",
27
+ "vite": "^7.3.1",
28
+ "vite-plugin-css-injected-by-js": "^4.0.1",
29
+ "vite-tsconfig-paths": "^6.0.1"
30
+ },
31
+ "devDependencies": {
32
+ "@types/minimist": "^1.2.5"
31
33
  }
32
34
  }
@@ -0,0 +1,50 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+
4
+ const DEFAULT_ENTRYPOINTS = [
5
+ "src/index.ts",
6
+ "src/index.tsx",
7
+ "src/index.js",
8
+ "src/index.jsx",
9
+ "index.ts",
10
+ "index.tsx",
11
+ "index.js",
12
+ "index.jsx",
13
+ ];
14
+
15
+ /**
16
+ * Resolves the application entry point.
17
+ * Uses the provided entryPoint, otherwise falls back to defaults.
18
+ * Throws a simple error if no valid entry file is found.
19
+ *
20
+ * @param {string} [entryPoint] - Entry point passed via CLI
21
+ * @returns {string} Absolute path to resolved entry file
22
+ */
23
+ const resolveEntryPoint = (entryPoint) => {
24
+ const consumerRoot = process.cwd();
25
+
26
+ // Use CLI entryPoint if provided
27
+ if (entryPoint) {
28
+ const resolvedPath = path.isAbsolute(entryPoint)
29
+ ? entryPoint
30
+ : path.resolve(consumerRoot, entryPoint);
31
+
32
+ if (!fs.existsSync(resolvedPath)) {
33
+ throw new Error(`[profile-scripts] entryPoint not found: ${entryPoint}`);
34
+ }
35
+
36
+ return resolvedPath;
37
+ }
38
+
39
+ // Resolve from defaults
40
+ for (const candidate of DEFAULT_ENTRYPOINTS) {
41
+ const fullPath = path.resolve(consumerRoot, candidate);
42
+ if (fs.existsSync(fullPath)) {
43
+ return fullPath;
44
+ }
45
+ }
46
+
47
+ throw new Error(`[profile-scripts] entryPoint not found`);
48
+ };
49
+
50
+ export default resolveEntryPoint;
@@ -0,0 +1,195 @@
1
+ import http from "http";
2
+ import fs from "node:fs";
3
+ import path from "path";
4
+ import { pathToFileURL } from "url";
5
+
6
+ import federation from "@originjs/vite-plugin-federation";
7
+ import react from "@vitejs/plugin-react";
8
+ import { transform } from "esbuild";
9
+ import minimist from "minimist";
10
+ import handler from "serve-handler";
11
+ import { build as viteBuild } from "vite";
12
+ import cssInjectedByJsPlugin from "vite-plugin-css-injected-by-js";
13
+ import tsconfigPaths from "vite-tsconfig-paths";
14
+
15
+ import resolveEntryPoint from "./utils/resolveEntryPoint.mjs";
16
+ import notifierPlugin from "./vitePlugins/viteNotifierPlugin.mjs";
17
+ import svgPlugin from "./vitePlugins/viteSvgPlugin.mjs";
18
+
19
+ const {
20
+ watch,
21
+ entryPoint,
22
+ externalGlobal,
23
+ federation: enableFederation,
24
+ } = minimist(process.argv.slice(2));
25
+
26
+ const consumerRoot = process.cwd();
27
+ const outDir = "build";
28
+
29
+ const entryAbs = resolveEntryPoint(entryPoint);
30
+
31
+ // Force JSX transform for .js files in src
32
+ const jsxPreTransformPlugin = {
33
+ name: "jsx-pre-transform",
34
+ enforce: "pre",
35
+ async transform(code, id) {
36
+ if (id.endsWith(".js") && id.includes(path.resolve(consumerRoot, "src"))) {
37
+ const result = await transform(code, {
38
+ loader: "jsx",
39
+ jsx: "automatic",
40
+ target: "esnext",
41
+ sourcemap: !watch,
42
+ });
43
+
44
+ return {
45
+ code: result.code,
46
+ map: result.map || null,
47
+ };
48
+ }
49
+ return null;
50
+ },
51
+ };
52
+
53
+ // Custom plugin to resolve package.json imports from node_modules
54
+ const packageJsonResolver = {
55
+ name: "package-json-resolver",
56
+ enforce: "pre",
57
+ resolveId(source) {
58
+ if (!source.endsWith("/package.json")) return null;
59
+
60
+ const pkgName = source.replace(/\/package\.json$/, "");
61
+
62
+ const resolvedPath = path.resolve(
63
+ consumerRoot,
64
+ "node_modules",
65
+ pkgName,
66
+ "package.json",
67
+ );
68
+
69
+ if (fs.existsSync(resolvedPath)) {
70
+ return resolvedPath;
71
+ }
72
+
73
+ return null;
74
+ },
75
+ };
76
+
77
+ // Parse external globals
78
+ const externalGlobals = externalGlobal
79
+ ? (typeof externalGlobal === "string"
80
+ ? [externalGlobal]
81
+ : externalGlobal
82
+ ).reduce((acc, curr) => {
83
+ const [key, value] = curr.split("=");
84
+ acc[key] = value;
85
+ return acc;
86
+ }, {})
87
+ : {};
88
+
89
+ // Dynamically resolve optional federation.config.(js|mjs) from consumer root
90
+ const resolveFederationConfig = async () => {
91
+ if (!enableFederation) return {};
92
+
93
+ const candidates = ["federation.config.mjs", "federation.config.js"];
94
+
95
+ for (const file of candidates) {
96
+ const fullPath = path.resolve(consumerRoot, file);
97
+ if (fs.existsSync(fullPath)) {
98
+ const mod = await import(pathToFileURL(fullPath).href);
99
+ return mod.default ?? mod;
100
+ }
101
+ }
102
+
103
+ throw new Error(
104
+ "[profile-scripts] --federation requires federation.config.(js|mjs) in project root.",
105
+ );
106
+ };
107
+
108
+ // Vite plugins
109
+ const vitePlugins = [
110
+ // Must run before other plugins: transforms JSX inside .js files
111
+ // so Vite's import analysis can parse them correctly
112
+ jsxPreTransformPlugin,
113
+
114
+ // Custom resolver for package.json imports
115
+ packageJsonResolver,
116
+
117
+ // React JSX transform + automatic runtime
118
+ react({
119
+ jsxRuntime: "automatic",
120
+ include: /\.(js|jsx|ts|tsx)$/,
121
+ }),
122
+
123
+ // Resolve tsconfig path aliases
124
+ tsconfigPaths(),
125
+
126
+ // Inject CSS into the bundle for library consumers without needing separate CSS files
127
+ cssInjectedByJsPlugin(),
128
+
129
+ // Handle SVG as React components or assets
130
+ svgPlugin(),
131
+
132
+ // Log build and rebuild status to console
133
+ notifierPlugin(Boolean(watch)),
134
+ ];
135
+
136
+ // Inject Module Federation support when --federation flag is provided
137
+ if (enableFederation) {
138
+ const federationConfig = await resolveFederationConfig();
139
+ vitePlugins.push(federation(federationConfig));
140
+ }
141
+
142
+ /**
143
+ * Vite build configuration
144
+ * @type {import('vite').UserConfig}
145
+ */
146
+ const viteConfig = {
147
+ root: consumerRoot,
148
+ plugins: vitePlugins,
149
+ logLevel: watch ? "error" : "info",
150
+ build: {
151
+ outDir,
152
+ emptyOutDir: true,
153
+ target: "esnext",
154
+ sourcemap: watch,
155
+ chunkSizeWarningLimit: 3000,
156
+ rollupOptions: {
157
+ input: entryAbs,
158
+ external: [
159
+ "react",
160
+ "react-dom",
161
+ "react-router-dom",
162
+ "IMTFPlugins",
163
+ ...Object.keys(externalGlobals),
164
+ ],
165
+ output: {
166
+ entryFileNames: "index.js",
167
+ format: "iife",
168
+ inlineDynamicImports: false,
169
+ globals: {
170
+ react: "React",
171
+ "react-dom": "ReactDOM",
172
+ "react-router-dom": "reactRouterDom",
173
+ IMTFPlugins: "IMTFPlugins",
174
+ ...externalGlobals,
175
+ },
176
+ },
177
+ },
178
+ minify: watch ? false : process.env.IMTF_MINIFY_WEBAPP !== "false",
179
+ watch: watch ? {} : null,
180
+ },
181
+ };
182
+
183
+ // Run Vite build in either watch or build mode
184
+ if (watch) {
185
+ await viteBuild(viteConfig);
186
+
187
+ http
188
+ .createServer((...params) => handler(...params, { public: outDir }))
189
+ .listen(3010, () => {
190
+ // eslint-disable-next-line no-console
191
+ console.log("Running at http://localhost:3010");
192
+ });
193
+ } else {
194
+ await viteBuild(viteConfig);
195
+ }
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Logs Vite build and rebuild status with rebuild count.
3
+ * Distinguishes initial build vs subsequent rebuilds in watch mode.
4
+ *
5
+ * @param {boolean} watch - Whether running in watch mode
6
+ * @returns {import('vite').Plugin}
7
+ */
8
+ const viteNotifierPlugin = (watch) => {
9
+ let isFirstBuild = true;
10
+ let rebuildCount = 0;
11
+
12
+ return {
13
+ name: "notifier-plugin-vite",
14
+
15
+ buildEnd(error) {
16
+ if (error) return;
17
+
18
+ if (!watch) {
19
+ console.log("Successfully built");
20
+ return;
21
+ }
22
+
23
+ if (isFirstBuild) {
24
+ console.log(`1st build: ${Date.now()}`);
25
+ isFirstBuild = false;
26
+ return;
27
+ }
28
+
29
+ rebuildCount += 1;
30
+ console.log(`Rebuilt (${rebuildCount}): ${Date.now()}`);
31
+ },
32
+ };
33
+ };
34
+
35
+ export default viteNotifierPlugin;
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Vite plugin to transform SVG imports based on project conventions.
3
+ *
4
+ * - SVGs outside `src/` or inside `src/assets/` are converted to base64 data URLs
5
+ * - SVGs inside `src/` are transformed into React components using SVGR
6
+ *
7
+ * @param {Object} [options] - SVGR configuration options
8
+ * @returns {import('vite').Plugin}
9
+ */
10
+ const viteSvgPlugin = (options = {}) => {
11
+ return {
12
+ name: "vite-svgr-plugin",
13
+ enforce: "pre",
14
+ async transform(code, id) {
15
+ if (!id.endsWith(".svg")) {
16
+ return null;
17
+ }
18
+ const svgPath = id.split("?")[0].split("#")[0];
19
+
20
+ // Read file content
21
+ const svg = await fs.promises.readFile(svgPath, "utf8");
22
+
23
+ // Determine relative path
24
+ const relativePath = path.relative(process.cwd(), svgPath);
25
+
26
+ // This is an asset ==> dataurl
27
+ if (
28
+ !relativePath.startsWith("src/") ||
29
+ relativePath.startsWith("src/assets/")
30
+ ) {
31
+ const dataurl = `data:image/svg+xml;base64,${Buffer.from(svg).toString("base64")}`;
32
+ return {
33
+ code: `export default ${JSON.stringify(dataurl)};`,
34
+ map: null
35
+ };
36
+ }
37
+
38
+ // Otherwise it's a react component
39
+ const contents = await transform(
40
+ svg,
41
+ {
42
+ plugins: ["@svgr/plugin-svgo", "@svgr/plugin-jsx"],
43
+ ...options
44
+ },
45
+ { filePath: svgPath }
46
+ );
47
+
48
+ return {
49
+ code: contents,
50
+ map: null
51
+ };
52
+ }
53
+ };
54
+ }
55
+
56
+ export default viteSvgPlugin;
@@ -1,94 +0,0 @@
1
- import { build, context } from "esbuild";
2
- import esbuild from "esbuild-plugin-external-global";
3
- import InlineCSSPlugin from "esbuild-plugin-inline-css";
4
- import CssModulesPlugin from "esbuild-css-modules-plugin";
5
- import minimist from "minimist";
6
- import HttpServer from "http-server";
7
-
8
- // eslint-disable-next-line import/no-named-as-default-member
9
- const externalGlobalPlugin = esbuild.externalGlobalPlugin;
10
-
11
- import notifierPlugin from "./notifierPlugin.mjs";
12
- import svgPlugin from "./svgPlugin.mjs";
13
-
14
- const {
15
- watch,
16
- entryPoint,
17
- externalGlobal,
18
- outbase = "src",
19
- } = minimist(process.argv.slice(2));
20
-
21
- const externalGlobals = externalGlobal
22
- ? (typeof externalGlobal === "string"
23
- ? [externalGlobal]
24
- : externalGlobal
25
- ).reduce((acc, curr) => {
26
- const [key, value] = curr.split("=");
27
- acc[key] = value;
28
- return acc;
29
- }, {})
30
- : {};
31
-
32
- const entryPoints = entryPoint
33
- ? typeof entryPoint === "string"
34
- ? [entryPoint]
35
- : entryPoint
36
- : ["src/index.js"];
37
-
38
- /**
39
- * @type {import('esbuild').BuildOptions}
40
- */
41
- const config = {
42
- entryPoints,
43
- outbase,
44
- outdir: "build",
45
- platform: "browser",
46
- bundle: true,
47
- target: "es2024",
48
- metafile: true,
49
-
50
- sourcemap: watch ? "linked" : "external",
51
-
52
- minify: watch === true ? false : process.env.IMTF_MINIFY_WEBAPP !== "false",
53
-
54
- loader: {
55
- // Enable JSX in .js files too
56
- ".js": "jsx",
57
- // Embed fonts
58
- ".eot": "dataurl",
59
- ".ttf": "dataurl",
60
- ".woff": "dataurl",
61
- ".woff2": "dataurl",
62
- // Embed images
63
- ".gif": "dataurl",
64
- ".jpg": "dataurl",
65
- ".png": "dataurl",
66
- },
67
-
68
- plugins: [
69
- CssModulesPlugin({ inject: true }),
70
- InlineCSSPlugin(),
71
- svgPlugin(),
72
- externalGlobalPlugin({
73
- react: "window.React",
74
- "react-dom": "window.ReactDOM",
75
- "react-router-dom": "window.reactRouterDom",
76
- IMTFPlugins: "window.IMTFPlugins",
77
- ...externalGlobals,
78
- }),
79
- notifierPlugin(watch),
80
- ],
81
- };
82
-
83
- if (watch) {
84
- const ctx = await context(config);
85
-
86
- // Enable watch mode
87
- await ctx.watch();
88
-
89
- // Create a server for the build directory
90
- const server = HttpServer.createServer({ root: "build" });
91
- server.listen(3010, () => console.log("Running at http://localhost:3010"));
92
- } else {
93
- await build(config);
94
- }
@@ -1,24 +0,0 @@
1
- const notifierPlugin = (watch) => ({
2
- name: "svgr",
3
- setup(build) {
4
- let count = 0;
5
-
6
- build.onEnd((result) => {
7
- if (result.errors.length > 0) {
8
- return;
9
- }
10
-
11
- if (count++ === 0) {
12
- if(watch) {
13
- console.log(`1st build: ${new Date().getTime()}`);
14
- } else {
15
- console.log(`Successfully built`);
16
- }
17
- } else {
18
- console.log(`Rebuilt: ${new Date().getTime()}`);
19
- }
20
- });
21
- },
22
- });
23
-
24
- export default notifierPlugin;
@@ -1,44 +0,0 @@
1
- import { transform } from "@svgr/core";
2
- import fs from "fs";
3
- import path from "path";
4
-
5
- const svgPlugin = (options = {}) => ({
6
- name: "svgr",
7
- setup(build) {
8
- build.onLoad({ filter: /\.svg$/ }, async (args) => {
9
- // Read file content
10
- const svg = await fs.promises.readFile(args.path, "utf8");
11
-
12
- // Determine relative path
13
- const relativePath = path.relative(process.cwd(), args.path);
14
-
15
- // This is an asset ==> dataurl
16
- if (
17
- !relativePath.startsWith("src/") ||
18
- relativePath.startsWith("src/assets/")
19
- ) {
20
- return {
21
- contents: svg,
22
- loader: "dataurl",
23
- };
24
- }
25
-
26
- // Otherwise it's a react component
27
- const contents = await transform(
28
- svg,
29
- {
30
- plugins: ["@svgr/plugin-svgo", "@svgr/plugin-jsx"],
31
- ...options,
32
- },
33
- { filePath: args.path }
34
- );
35
-
36
- return {
37
- contents,
38
- loader: "jsx",
39
- };
40
- });
41
- },
42
- });
43
-
44
- export default svgPlugin;