Prepare applications for deployment via CI
A common approach to deploying applications is via docker containers. Some applications can be built into bundles that are environment agnostic, while others depend on OS-specific packages being installed. For these situations, having just bundled code is not enough, we also need to have package.json
.
Nx supports the generation of the project's package.json
by identifying all the project's dependencies. The generated package.json
is created next to the built artifacts (usually at dist/apps/name-of-the-app
).
Additionally, we should generate pruned lock file according to the generated package.json
. This makes the installation in the container significantly faster as we only need to install a subset of the packages.
Nx offers two varieties of Webpack plugin which can be used to generate package.json
.
Basic Plugin Configuration
@nx/webpack/plugin
plugin is compatible with a conventional webpack configuration setup which offers a smooth integration with the Webpack CLI. It is configured in the plugins
array in nx.json
.
1{
2 "plugins": [
3 {
4 "plugin": "@nx/webpack/plugin",
5 "options": {
6 "buildTargetName": "build",
7 "serveTargetName": "serve",
8 "serveStaticTargetName": "serve-static",
9 "previewStaticTargetName": "preview"
10 }
11 }
12 ]
13}
14
Where build
, serve
, serve-static
and preview
in conjunction with your webpack.config.js
are the names of the targets that are used to build, serve, and preview the application respectively.
NxWebpackPlugin
The NxWebpackPlugin
plugin takes a main
entry file and produces a bundle in the output directory as defined in output.path
. You can also pass the index
option if it is a web app, which will handle outputting scripts and stylesheets in the output file.
To generate a package.json
we would declare it in the plugin options.
1const { NxWebpackPlugin } = require('@nx/webpack');
2const { join } = require('path');
3
4module.exports = {
5 output: {
6 path: join(__dirname, '../../dist/apps/acme'),
7 },
8 devServer: {
9 port: 4200,
10 },
11 plugins: [
12 new NxWebpackPlugin({
13 tsConfig: './tsconfig.app.json',
14 compiler: 'swc',
15 main: './src/main.tsx',
16 index: '.src/index.html',
17 styles: ['./src/styles.css'],
18 generatePackageJson: true,
19 }),
20 ],
21};
22
Programmtic usage
If you using a custom setup that does not support the creation of a package.json
or a lock file, you can still use Nx to generate them via The createPackageJson
and createLockFile
functions which are exported from @nx/js
:
If you need to use a custom script, to build your application it should look similar to the following:
1const {
2 createProjectGraphAsync,
3 readCachedProjectGraph,
4 detectPackageManager,
5} = require('@nx/devkit');
6const {
7 createLockFile,
8 createPackageJson,
9 getLockFileName,
10} = require('@nx/js');
11const { writeFileSync } = require('fs');
12
13async function main() {
14 const outputDir = 'dist'; // You can replace this with the output directory you want to use
15 // Detect the package manager you are using (npm, yarn, pnpm)
16 const pm = detectPackageManager();
17 let projectGraph = readCachedProjectGraph();
18 if (!projectGraph) {
19 projectGraph = await createProjectGraphAsync();
20 }
21 // You can replace <NX_TASK_TARGET_PROJECT> with the name of the project if you want.
22 const projectName = process.env.NX_TASK_TARGET_PROJECT;
23 const packageJson = createPackageJson(projectName, projectGraph, {
24 isProduction: true, // Used to strip any non-prod dependencies
25 root: projectGraph.nodes[projectName].data.root,
26 });
27
28 const lockFile = createLockFile(
29 packageJson,
30 projectGraph,
31 detectPackageManager()
32 );
33
34 const lockFileName = getLockFileName(pm);
35
36 writeFileSync(`${outputDir}/package.json`, packageJson);
37 writeFileSync(`${outputDir}/${lockFileName}`, lockFile, {
38 encoding: 'utf8',
39 });
40
41 //... Any additional steps you want to run
42}
43
44main();
45
Then to run the script, update your package.json
to include the following:
1{
2 "scripts": {
3 "copy-package-json": "node scripts/create-package-json.js",
4 "custom-build": "nx build && npm run copy-package-json"
5 }
6}
7
Now, you can run npm run custom-build
to build your application and generate the package.json
and lock file.
You can replace npm with yarn or pnpm if you are using those package managers.
Vite is a build tool that is great for development, and we want to make sure that it is also great for production. We are working on a plugin for Vite that will have parity with the Webpack plugin. Stay tuned for updates.