Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs(webpack): Add docs for webpack ci deployment #21650

Merged
merged 2 commits into from
Feb 7, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
155 changes: 150 additions & 5 deletions docs/shared/recipes/ci-deployment.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,69 @@ Nx supports the generation of the project's `package.json` by identifying all th

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`.

{% tabs %}

{% tab label="Nx 18+" %}

## 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`.

```json {% fileName="nx.json" %}
{
"plugins": [
{
"plugin": "@nx/webpack/plugin",
"options": {
"buildTargetName": "build",
"serveTargetName": "serve",
"serveStaticTargetName": "serve-static",
"previewStaticTargetName": "preview"
}
}
]
}
```

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`](/recipes/webpack/webpack-plugins#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.

```js {% fileName="apps/acme/app/webpack.config.js" %}
const { NxWebpackPlugin } = require('@nx/webpack');
const { join } = require('path');

module.exports = {
output: {
path: join(__dirname, '../../dist/apps/acme'),
},
devServer: {
port: 4200,
},
plugins: [
new NxWebpackPlugin({
tsConfig: './tsconfig.app.json',
compiler: 'swc',
main: './src/main.tsx',
index: '.src/index.html',
styles: ['./src/styles.css'],
generatePackageJson: true,
}),
],
};
```

{% /tab %}

{% tab label="Nx < 18" %}

## Supported executors

The `@nx/webpack:webpack` executor supports the `generatePackageJson` flag which generates both `package.json` as well as the lock file.
Expand All @@ -16,12 +79,87 @@ Some executors automatically generate output `package.json` and the lock file ge
- `@nx/js:tsc`
- `@nx/next:build`

## Using a custom executor
{% /tab %}
{% /tabs %}

## Programmtic usage

If you are 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`:

{% tabs %}

{% tab label="Custom script" %}

If you are using a custom executor or an executor that does not support `generatePackgeJson` or `generateLockfile` flags, you can still use Nx to generate `package.json` and the lock file. The `createPackageJson` and `createLockFile` functions are exported from `@nx/devkit`:
If you need to use a custom script, to build your application it should look similar to the following:

```javascript {% fileName="scripts/create-package-json.js" %}
const {
createProjectGraphAsync,
readCachedProjectGraph,
detectPackageManager,
} = require('@nx/devkit');
const {
createLockFile,
createPackageJson,
getLockFileName,
} = require('@nx/js');
const { writeFileSync } = require('fs');

async function main() {
const outputDir = 'dist'; // You can replace this with the output directory you want to use
// Detect the package manager you are using (npm, yarn, pnpm)
const pm = detectPackageManager();
let projectGraph = readCachedProjectGraph();
if (!projectGraph) {
projectGraph = await createProjectGraphAsync();
}
// You can replace <NX_TASK_TARGET_PROJECT> with the name of the project if you want.
const projectName = process.env.NX_TASK_TARGET_PROJECT;
const packageJson = createPackageJson(projectName, projectGraph, {
isProduction: true, // Used to strip any non-prod dependencies
root: projectGraph.nodes[projectName].data.root,
});

const lockFile = createLockFile(
packageJson,
projectGraph,
detectPackageManager()
);

const lockFileName = getLockFileName(pm);

writeFileSync(`${outputDir}/package.json`, packageJson);
writeFileSync(`${outputDir}/${lockFileName}`, lockFile, {
encoding: 'utf8',
});

//... Any additional steps you want to run
}

main();
```

Then to run the script, update your `package.json` to include the following:

```json {% fileName="package.json" %}
{
"scripts": {
"copy-package-json": "node scripts/create-package-json.js",
"custom-build": "nx build && npm run copy-package-json"
}
}
```

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.

{% /tab %}

{% tab label="Custom executor" %}

```typescript
import { createPackageJson, createLockFile } from '@nx/devkit';
import { createPackageJson, createLockFile } from '@nx/js';
import { writeFileSync } from 'fs';

export default async function buildExecutor(
Expand All @@ -42,11 +180,18 @@ export default async function buildExecutor(
// do any additional manipulations to "package.json" here

const lockFile = createLockFile(packageJson);
writeJsonFile(`${options.outputPath}/package.json`, builtPackageJson);
writeFileSync(`${options.outputPath}/${packageLockFileName}}`, lockFile, {
writeJsonFile(`${options.outputPath}/package.json`, packageJson);
writeFileSync(`${options.outputPath}/${packageLockFileName}`, lockFile, {
encoding: 'utf-8',
});

// any subsequent executor code
}
```

{% /tab %}
{% /tabs %}

{% callout type="note" title="What about Vite?" %}
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 an `NxVitePlugin` plugin for Vite that will have parity with the `NxWebpackPlugin`. Stay tuned for updates.
{% /callout %}