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,28 +173,36 @@ 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
+
".": "./dist/index.js",
184
+
"./app.scss": "./dist/app.scss"
185
+
},
158
186
```
159
187
188
+
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.
189
+
160
190
files
161
191
-----
162
192
163
-
This is a buildless library, so we package files in `src`:
193
+
Package the compiled output in `dist`:
164
194
165
195
```json
166
196
"files": [
167
-
"/src"
197
+
"/dist"
168
198
],
169
199
```
170
200
171
201
sideEffects
172
202
-----------
173
203
174
-
This means that the code from the library can be safely tree-shaken by webpack.
204
+
This tells webpack that the code from the library can be safely tree-shaken, except
205
+
for CSS/SCSS files which are imported purely for their side effects.
175
206
176
207
```json
177
208
"sideEffects": [
@@ -196,15 +227,10 @@ Finally, make sure the following fields are set properly:
196
227
Clean up .npmignore
197
228
===================
198
229
199
-
This is what should be in the repo's `.npmignore`. No more, no less:
230
+
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
231
201
232
```
202
-
__mocks__
203
233
node_modules
204
-
*.test.js
205
-
*.test.jsx
206
-
*.test.ts
207
-
*.test.tsx
208
234
```
209
235
210
236
Clean up .gitignore
@@ -257,10 +283,13 @@ Create a `tsconfig.json` file and add the following contents to it:
@@ -275,6 +304,53 @@ Create a `tsconfig.json` file and add the following contents to it:
275
304
276
305
This assumes you have a `src` folder and your build goes in `dist`, which is the best practice.
277
306
307
+
The `@src` path alias
308
+
---------------------
309
+
310
+
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.
321
+
322
+
Add a tsconfig.build.json file
323
+
------------------------------
324
+
325
+
Create a `tsconfig.build.json` file for compiling your app before publishing:
326
+
327
+
```json
328
+
{
329
+
"extends": "./tsconfig.json",
330
+
"compilerOptions": {
331
+
"rootDir": "src",
332
+
"outDir": "dist",
333
+
"noEmit": false
334
+
},
335
+
"include": [
336
+
"src/**/*"
337
+
],
338
+
"exclude": [
339
+
"src/**/*.test.ts",
340
+
"src/**/*.test.tsx",
341
+
"src/**/*.spec.ts",
342
+
"src/**/*.spec.tsx",
343
+
"src/__mocks__/**/*",
344
+
"src/setupTest.js"
345
+
]
346
+
}
347
+
```
348
+
349
+
This config:
350
+
- Extends your main `tsconfig.json`
351
+
- Outputs compiled JavaScript and type declarations to `dist/`
352
+
- Excludes test files and mocks from the published package
353
+
278
354
279
355
Edit jest.config.js
280
356
===================
@@ -283,7 +359,7 @@ Replace the import from 'frontend-build' with 'frontend-base'.
@@ -494,14 +570,14 @@ SVGR "ReactComponent" imports have been removed
494
570
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
571
496
572
497
-
Import createConfig and getBaseConfig from @openedx/frontend-base/config
573
+
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 +950,3 @@ Refactor slots
874
950
First, rename `src/plugin-slots`, if it exists, to `src/slots`. Modify imports and documentation across the codebase accordingly.
875
951
876
952
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