You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Ship compiled JavaScript + .d.ts declarations instead of raw TypeScript
source. This allows consuming apps to also pre-compile their TypeScript
and use tsc-alias to resolve arbitrary paths (such as @src).
At the bundler level, we add tsconfig-paths-webpack-plugin to Webpack
configuration so that the Typescript aliases can also be used by Webpack
builds without duplicating their definition.
As part of this, unify the tsc builds so that everything ends up in
/dist, and then use more modern export maps to decouple the internal
file structure from the package's API.
Of note, the default tsconfig (not the one used by tools) now uses
`moduleResolution: bundler` to allow for more modern entrypoint
definition.
BREAKING CHANGE: consuming apps need to modify their imports and
configuration accordingly. See the changes in the migration howto for
details.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
@@ -137,6 +138,28 @@ With the exception of any custom scripts, replace the `scripts` section of your
137
138
},
138
139
```
139
140
141
+
The `build` script invokes a Makefile target. You'll need to install `tsc-alias` as a dev dependency:
142
+
143
+
```sh
144
+
npm install --save-dev tsc-alias
145
+
```
146
+
147
+
Then add a `build:` target to your `Makefile`:
148
+
149
+
```makefile
150
+
build:
151
+
tsc --project tsconfig.build.json
152
+
tsc-alias -p tsconfig.build.json
153
+
find src -type f -name '*.scss' -exec sh -c '\
154
+
forfin"$$@";do \
155
+
d="dist/$${f#src/}";\
156
+
mkdir -p "$$(dirname "$$d")";\
157
+
cp "$$f""$$d";\
158
+
done' sh {} +
159
+
```
160
+
161
+
This target compiles TypeScript to JavaScript, uses `tsc-alias` to rewrite `@src` path aliases to relative paths, and copies all SCSS files from `src/` into `dist/` preserving directory structure.
162
+
140
163
- Replace `YOUR_PORT` with the desired port, of course.
141
164
- Replace `YOUR_APP_NAME` with the basename used on your site.config, not doing this will result in only the root route working.
142
165
- Note that `fedx-scripts` no longer exists, and has been replaced with `openedx`.
@@ -150,21 +173,32 @@ Other package.json edits
150
173
151
174
- Change the author to "Open edX"
152
175
153
-
main
154
-
----
176
+
exports
177
+
-------
178
+
179
+
DefinethepublicAPIforyourpackage:
155
180
156
181
```json
157
-
"main": "src/index.ts",
182
+
"exports": {
183
+
".": {
184
+
"types": "./dist/index.d.ts",
185
+
"import": "./dist/index.js",
186
+
"default": "./dist/index.js"
187
+
},
188
+
"./app.scss": "./dist/app.scss"
189
+
},
158
190
```
159
191
192
+
The `exports` map decouples your public API from the internal `dist/` directory structure. Consumers import from clean paths (e.g., `@openedx/frontend-app-yourapp/app.scss`) and the map resolves them to the actual files in `dist/`. If your app has SCSS files that downstream site projects need to `@use`, add them as exports as shown above.
193
+
160
194
files
161
195
-----
162
196
163
-
This is a buildless library, so we package files in `src`:
197
+
Package the compiled output in `dist`:
164
198
165
199
```json
166
200
"files": [
167
-
"/src"
201
+
"/dist"
168
202
],
169
203
```
170
204
@@ -175,8 +209,8 @@ This means that the code from the library can be safely tree-shaken by webpack.
175
209
176
210
```json
177
211
"sideEffects": [
178
-
"*.css",
179
-
"*.scss"
212
+
"dist/**/*.css",
213
+
"dist/**/*.scss"
180
214
],
181
215
```
182
216
@@ -196,15 +230,10 @@ Finally, make sure the following fields are set properly:
196
230
Clean up .npmignore
197
231
===================
198
232
199
-
This is what should be in the repo's `.npmignore`. No more, no less:
233
+
Since we use the `files` field in `package.json` to whitelist only `/dist`, the `.npmignore` file is largely unnecessary. You can keep a minimal version:
200
234
201
235
```
202
-
__mocks__
203
236
node_modules
204
-
*.test.js
205
-
*.test.jsx
206
-
*.test.ts
207
-
*.test.tsx
208
237
```
209
238
210
239
Clean up .gitignore
@@ -257,10 +286,14 @@ Create a `tsconfig.json` file and add the following contents to it:
@@ -275,6 +308,53 @@ Create a `tsconfig.json` file and add the following contents to it:
275
308
276
309
This assumes you have a `src` folder and your build goes in `dist`, which is the best practice.
277
310
311
+
The `@src` path alias
312
+
---------------------
313
+
314
+
The `paths` configuration above sets up the `@src` alias, which allows you to import from your app's `src` directory using `@src/...` instead of relative paths. For example:
For this to work, the app must define its own `@src` path mapping in `tsconfig.json`. **tsc-alias** will then rewrite `@src` imports to relative paths during the build step, so the compiled JavaScript has proper paths.
325
+
326
+
Add a tsconfig.build.json file
327
+
------------------------------
328
+
329
+
Create a `tsconfig.build.json` file for compiling your app before publishing:
330
+
331
+
```json
332
+
{
333
+
"extends": "./tsconfig.json",
334
+
"compilerOptions": {
335
+
"rootDir": "src",
336
+
"outDir": "dist",
337
+
"noEmit": false
338
+
},
339
+
"include": [
340
+
"src/**/*"
341
+
],
342
+
"exclude": [
343
+
"src/**/*.test.ts",
344
+
"src/**/*.test.tsx",
345
+
"src/**/*.spec.ts",
346
+
"src/**/*.spec.tsx",
347
+
"src/__mocks__/**/*",
348
+
"src/setupTest.js"
349
+
]
350
+
}
351
+
```
352
+
353
+
This config:
354
+
- Extends your main `tsconfig.json`
355
+
- Outputs compiled JavaScript and type declarations to `dist/`
356
+
- Excludes test files and mocks from the published package
357
+
278
358
279
359
Edit jest.config.js
280
360
===================
@@ -283,7 +363,7 @@ Replace the import from 'frontend-build' with 'frontend-base'.
@@ -494,14 +574,14 @@ SVGR "ReactComponent" imports have been removed
494
574
We have removed the `@svgr/webpack` loader because it was incompatible with more modern tooling (it requires Babel). As a result, the ability to import SVG files into JS as the `ReactComponent` export no longer works. We know of a total of 5 places where this is happening today in Open edX MFEs - frontend-app-learning and frontend-app-profile use it. Please replace that export with the default URL export and set the URL as the source of an `<img>` tag, rather than using `ReactComponent`. You can see an example of normal SVG imports in `test-site/src/ExamplePage.tsx`.
495
575
496
576
497
-
Import createConfig and getBaseConfig from @openedx/frontend-base/config
577
+
Import createConfig and getBaseConfig from @openedx/frontend-base/tools
In frontend-build, `createConfig` and `getBaseConfig` could be imported from the root package (`@openedx/frontend-build`). They have been moved to a sub-directory to make room for runtime exports from the root package (`@openedx/frontend-base`).
You may have handled this in steps 4 and 5 above (jest.config.js and .eslintrc.js)
@@ -874,19 +954,3 @@ Refactor slots
874
954
First, rename `src/plugin-slots`, if it exists, to `src/slots`. Modify imports and documentation across the codebase accordingly.
875
955
876
956
Next, the frontend-base equivalent to `<PluginSlot />` is `<Slot />`, and has a different API. This includes a change in the slot ID, according to the [new slot naming ADR](../decisions/0009-slot-naming-and-lifecycle.rst) in this repository. Rename them accordingly. You can refer to the `src/shell/dev` in this repository for examples.
877
-
878
-
879
-
Remove build step from CI
880
-
=========================
881
-
882
-
In `.github/workflow/ci.yml`, remove the build step.
0 commit comments