@prairielearn/compiled-assets
v4.0.1
Published
This package enables the transpilation and bundling of client-side assets, namely JavaScript.
Readme
@prairielearn/compiled-assets
This package enables the transpilation and bundling of client-side assets, namely JavaScript.
This tool is meant to produce many small, independent bundles that can then be included as needed on each page, as well as providing mechanisms for code splitting larger ESM bundles.
Usage
File structure
Create a directory of assets that you wish to bundle, e.g. assets/. Within that directory, create another directory scripts/. Any JavaScript or TypeScript files in the root of the scripts/ directory will become a bundle that can be loaded on a page. For example, the following directory structure would produce bundles named foo and bar:
├── assets/
│ ├── scripts/
│ │ ├── foo.ts
│ │ └── bar.tsYou can locate shared code in directories inside this directory. As long as those files aren't in the root of the scripts/ directory, they won't become separate bundles.
assets
└── scripts
├── bar.ts
├── foo.ts
└── lib
├── more-shared-code.ts
└── shared-code.tsThese assets will be output as an IIFE for compatibility reasons. You can place additional assets in the assets/scripts/esm-bundles/ directory, which will be output as ESM module files with code splitting. This is useful for libraries that can be loaded asynchronously, like React components.
assets
└── scripts
└── esm-bundles
└── baz.tsxThe import tree of all files will be analyzed, and any code-split chunks or dynamically-imported files will be marked as preloads.
Application integration
Early in your application initialization process, initialize this library with the appropriate options:
import * as compiledAssets from '@prairielearn/compiled-assets';
assets.init({
// Assets will be watched for changes in development mode, and the latest version will be served.
// In production mode, assets will be precompiled and served from the build directory.
dev: process.env.NODE_ENV !== 'production',
sourceDirectory: './assets',
buildDirectory: './public/build',
publicPath: '/build/',
});Then, add the request handler. The path at which you mount it should match the publicPath that was configured above.
const app = express();
app.use('/build/', assets.handler());To include a bundle on your page, you can use the compiledScriptTag or compiledScriptPath functions. The name of the bundle passed to this function is the filename of your bundle within the scripts directory.
If your file is located in the esm-bundles folder (and processed with ESM + code splitting), you can use the compiledScriptModuleTag function. You can use compiledScriptModulePreloadTags to get a list of tags that should be preloaded in the <head> of your HTML document.
import { html } from '@prairielearn/html';
import {
compiledScriptTag,
compiledScriptPath,
compiledScriptModuleTag,
} from '@prairielearn/compiled-assets';
router.get(() => {
return html`
<html>
<head>
${compiledScriptTag('foo.ts')}
<script src="${compiledScriptPath('bar.ts')}"></script>
${compiledScriptModuleTag('baz.tsx')}
</head>
</body>
Hello, world.
</body>
</html>
`;
});Building assets for production
For production usage, assets must be precompiled with the compiled-assets build command. Note that the source directory and build directory should match the values provided to assets.init.
compiled-assets build ./assets ./public/build