feat(react): support port option for react app generator (#31552)
This PR adds the ability to set the port of the React application when using the generator. e.g. ```shell npx nx g @nx/react:app --port 8080 ``` This is useful when generating multiple apps and then running them in parallel.
This commit is contained in:
parent
6bc4ef47ec
commit
40cf21b10c
@ -19,6 +19,10 @@
|
|||||||
{
|
{
|
||||||
"command": "nx g app apps/myapp --routing",
|
"command": "nx g app apps/myapp --routing",
|
||||||
"description": "Set up React Router"
|
"description": "Set up React Router"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "nx g app apps/myapp --port=3000",
|
||||||
|
"description": "Set up the dev server to use port 3000"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@ -190,6 +194,12 @@
|
|||||||
"useProjectJson": {
|
"useProjectJson": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Use a `project.json` configuration file instead of inlining the Nx configuration in the `package.json` file."
|
"description": "Use a `project.json` configuration file instead of inlining the Nx configuration in the `package.json` file."
|
||||||
|
},
|
||||||
|
"port": {
|
||||||
|
"type": "number",
|
||||||
|
"description": "The port to use for the development server",
|
||||||
|
"x-prompt": "Which port would you like to use for the dev server?",
|
||||||
|
"default": 4200
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["directory"],
|
"required": ["directory"],
|
||||||
|
|||||||
@ -55,6 +55,10 @@
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": ["node", "jsdom", "happy-dom", "edge-runtime"],
|
"enum": ["node", "jsdom", "happy-dom", "edge-runtime"],
|
||||||
"default": "jsdom"
|
"default": "jsdom"
|
||||||
|
},
|
||||||
|
"port": {
|
||||||
|
"type": "number",
|
||||||
|
"description": "The port to use for the development server"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"examplesFile": "---\ntitle: Examples for the Vite configuration generator\ndescription: This page contains examples for the Vite @nx/vite:configuration generator, which helps you set up Vite on your Nx workspace, or convert an existing project to use Vite.\n---\n\nThis generator is used for converting an existing React or Web project to use [Vite.js](https://vitejs.dev/).\n\nIt will create a `vite.config.ts` file at the root of your project with the correct settings, or if there's already a `vite.config.ts` file, it will modify it to include the correct settings.\n\n{% callout type=\"caution\" title=\"Your code will be modified!\" %}\nThis generator will modify your code, so make sure to commit your changes before running it.\n{% /callout %}\n\n```bash\nnx g @nx/vite:configuration\n```\n\nWhen running this generator, you will be prompted to provide the following:\n\n- The `project`, as the name of the project you want to generate the configuration for.\n- The `uiFramework` you want to use. Supported values are: `react` and `none`.\n\nYou must provide a `project` and a `uiFramework` for the generator to work.\n\nYou may also pass the `includeVitest` flag. This will also configure your project for testing with [Vitest](https://vitest.dev/), by adding the `test` configuration in your `vite.config.ts` file.\n\n## How to use\n\nIf you have an existing project that does not use Vite, you may want to convert it to use Vite. This can be a `webpack` project, a buildable JS library that uses the `@nx/js:babel`, the `@nx/js:swc` or the `@nx/rollup:rollup` executor, or even a non-buildable library.\nBy default, the `@nx/vite:configuration` generator will search your project to find the relevant configuration (either a `webpack.config.ts` file for example, or the `@nx/js` executors). If it determines that your project can be converted, then Nx will generate the configuration for you. If it cannot determine that your project can be converted, it will ask you if you want to convert it anyway or throw an error if it determines that it cannot be converted.\n\nYou can then test on your own if the result works or not, and modify the configuration as needed. It's suggested that you commit your changes before running the generator, so you can revert the changes if needed.\n\n## Projects that can be converted to use the `@nx/vite` executors\n\nUsually, React and Web projects generated with the `@nx/react` and the `@nx/web` generators can be converted to use the `@nx/vite` executors without any issues.\n\nThe list of executors for building, testing and serving that can be converted to use the `@nx/vite` executors is:\n\n### Supported `build` executors\n\n- `@nxext/vite:build`\n- `@nx/js:babel`\n- `@nx/js:swc`\n- `@nx/rollup:rollup`\n- `@nx/webpack:webpack`\n- `@nx/web:rollup`\n\n### Unsupported executors\n\n- `@nx/angular:ng-packagr-lite`\n- `@nx/angular:package`\n- `@nx/angular:webpack-browser`\n- `@angular-devkit/build-angular:browser`\n- `@angular-devkit/build-angular:dev-server`\n- `@nx/esbuild:esbuild`\n- `@nx/react-native:start`\n- `@nx/next:build`\n- `@nx/next:server`\n- `@nx/js:tsc`\n- any executor _not_ listed in the lists of \"supported executors\"\n- any project that does _not_ have a target for building, serving or testing\n\nWe **cannot** guarantee that projects using unsupported executors - _or any executor that is NOT listed in the list of \"supported executors\"_ - for either building, testing or serving will work correctly when converted to use Vite.\n\nYou can read more in the [Vite package overview page](/nx-api/vite).\n\n## Examples\n\n### Convert a React app to use Vite\n\n```bash\nnx g @nx/vite:configuration --project=my-react-app --uiFramework=react --includeVitest\n```\n\nThis will configure the `my-react-app` project to use Vite.\n\n### Convert a Web app to use Vite\n\n```bash\nnx g @nx/vite:configuration --project=my-web-app --uiFramework=none --includeVitest\n```\n\nThis will configure the `my-web-app` project to use Vite.\n",
|
"examplesFile": "---\ntitle: Examples for the Vite configuration generator\ndescription: This page contains examples for the Vite @nx/vite:configuration generator, which helps you set up Vite on your Nx workspace, or convert an existing project to use Vite.\n---\n\nThis generator is used for converting an existing React or Web project to use [Vite.js](https://vitejs.dev/).\n\nIt will create a `vite.config.ts` file at the root of your project with the correct settings, or if there's already a `vite.config.ts` file, it will modify it to include the correct settings.\n\n{% callout type=\"caution\" title=\"Your code will be modified!\" %}\nThis generator will modify your code, so make sure to commit your changes before running it.\n{% /callout %}\n\n```bash\nnx g @nx/vite:configuration\n```\n\nWhen running this generator, you will be prompted to provide the following:\n\n- The `project`, as the name of the project you want to generate the configuration for.\n- The `uiFramework` you want to use. Supported values are: `react` and `none`.\n\nYou must provide a `project` and a `uiFramework` for the generator to work.\n\nYou may also pass the `includeVitest` flag. This will also configure your project for testing with [Vitest](https://vitest.dev/), by adding the `test` configuration in your `vite.config.ts` file.\n\n## How to use\n\nIf you have an existing project that does not use Vite, you may want to convert it to use Vite. This can be a `webpack` project, a buildable JS library that uses the `@nx/js:babel`, the `@nx/js:swc` or the `@nx/rollup:rollup` executor, or even a non-buildable library.\nBy default, the `@nx/vite:configuration` generator will search your project to find the relevant configuration (either a `webpack.config.ts` file for example, or the `@nx/js` executors). If it determines that your project can be converted, then Nx will generate the configuration for you. If it cannot determine that your project can be converted, it will ask you if you want to convert it anyway or throw an error if it determines that it cannot be converted.\n\nYou can then test on your own if the result works or not, and modify the configuration as needed. It's suggested that you commit your changes before running the generator, so you can revert the changes if needed.\n\n## Projects that can be converted to use the `@nx/vite` executors\n\nUsually, React and Web projects generated with the `@nx/react` and the `@nx/web` generators can be converted to use the `@nx/vite` executors without any issues.\n\nThe list of executors for building, testing and serving that can be converted to use the `@nx/vite` executors is:\n\n### Supported `build` executors\n\n- `@nxext/vite:build`\n- `@nx/js:babel`\n- `@nx/js:swc`\n- `@nx/rollup:rollup`\n- `@nx/webpack:webpack`\n- `@nx/web:rollup`\n\n### Unsupported executors\n\n- `@nx/angular:ng-packagr-lite`\n- `@nx/angular:package`\n- `@nx/angular:webpack-browser`\n- `@angular-devkit/build-angular:browser`\n- `@angular-devkit/build-angular:dev-server`\n- `@nx/esbuild:esbuild`\n- `@nx/react-native:start`\n- `@nx/next:build`\n- `@nx/next:server`\n- `@nx/js:tsc`\n- any executor _not_ listed in the lists of \"supported executors\"\n- any project that does _not_ have a target for building, serving or testing\n\nWe **cannot** guarantee that projects using unsupported executors - _or any executor that is NOT listed in the list of \"supported executors\"_ - for either building, testing or serving will work correctly when converted to use Vite.\n\nYou can read more in the [Vite package overview page](/nx-api/vite).\n\n## Examples\n\n### Convert a React app to use Vite\n\n```bash\nnx g @nx/vite:configuration --project=my-react-app --uiFramework=react --includeVitest\n```\n\nThis will configure the `my-react-app` project to use Vite.\n\n### Convert a Web app to use Vite\n\n```bash\nnx g @nx/vite:configuration --project=my-web-app --uiFramework=none --includeVitest\n```\n\nThis will configure the `my-web-app` project to use Vite.\n",
|
||||||
|
|||||||
@ -22,6 +22,26 @@ describe('Build React applications and libraries with Rspack', () => {
|
|||||||
cleanupProject();
|
cleanupProject();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should generate app with custom port', async () => {
|
||||||
|
const appName = uniq('app');
|
||||||
|
const customPort = 8081;
|
||||||
|
|
||||||
|
runCLI(
|
||||||
|
`generate @nx/react:app ${appName} --bundler=rspack --port=${customPort} --unit-test-runner=vitest --no-interactive --skipFormat --linter=eslint --e2eTestRunner=playwright`
|
||||||
|
);
|
||||||
|
|
||||||
|
const rspackConfig = readFile(`${appName}/rspack.config.js`);
|
||||||
|
expect(rspackConfig).toContain(`port: ${customPort}`);
|
||||||
|
|
||||||
|
if (runE2ETests()) {
|
||||||
|
const e2eResults = runCLI(`e2e ${appName}-e2e`, {
|
||||||
|
verbose: true,
|
||||||
|
});
|
||||||
|
expect(e2eResults).toContain('Successfully ran target e2e for project');
|
||||||
|
expect(await killPorts()).toBeTruthy();
|
||||||
|
}
|
||||||
|
}, 300_000);
|
||||||
|
|
||||||
it('should be able to use Rspack to build and test apps', async () => {
|
it('should be able to use Rspack to build and test apps', async () => {
|
||||||
const appName = uniq('app');
|
const appName = uniq('app');
|
||||||
const libName = uniq('lib');
|
const libName = uniq('lib');
|
||||||
|
|||||||
@ -1,9 +1,12 @@
|
|||||||
import {
|
import {
|
||||||
checkFilesExist,
|
checkFilesExist,
|
||||||
cleanupProject,
|
cleanupProject,
|
||||||
|
killPorts,
|
||||||
newProject,
|
newProject,
|
||||||
|
readFile,
|
||||||
runCLI,
|
runCLI,
|
||||||
runCLIAsync,
|
runCLIAsync,
|
||||||
|
runE2ETests,
|
||||||
uniq,
|
uniq,
|
||||||
} from '@nx/e2e/utils';
|
} from '@nx/e2e/utils';
|
||||||
|
|
||||||
@ -60,6 +63,26 @@ describe('Build React applications and libraries with Vite', () => {
|
|||||||
checkFilesExist(`dist/apps/${viteApp}/index.html`);
|
checkFilesExist(`dist/apps/${viteApp}/index.html`);
|
||||||
}, 300_000);
|
}, 300_000);
|
||||||
|
|
||||||
|
it('should generate app with custom port', async () => {
|
||||||
|
const viteApp = uniq('viteapp');
|
||||||
|
const customPort = 8081;
|
||||||
|
|
||||||
|
runCLI(
|
||||||
|
`generate @nx/react:app apps/${viteApp} --bundler=vite --port=${customPort} --unitTestRunner=vitest --no-interactive --linter=eslint --e2eTestRunner=playwright`
|
||||||
|
);
|
||||||
|
|
||||||
|
const viteConfig = readFile(`apps/${viteApp}/vite.config.ts`);
|
||||||
|
expect(viteConfig).toContain(`port: ${customPort}`);
|
||||||
|
|
||||||
|
if (runE2ETests()) {
|
||||||
|
const e2eResults = runCLI(`e2e ${viteApp}-e2e`, {
|
||||||
|
verbose: true,
|
||||||
|
});
|
||||||
|
expect(e2eResults).toContain('Successfully ran target e2e for project');
|
||||||
|
expect(await killPorts()).toBeTruthy();
|
||||||
|
}
|
||||||
|
}, 300_000);
|
||||||
|
|
||||||
it('should test and lint app with bundler=vite and inSourceTests', async () => {
|
it('should test and lint app with bundler=vite and inSourceTests', async () => {
|
||||||
const viteApp = uniq('viteapp');
|
const viteApp = uniq('viteapp');
|
||||||
const viteLib = uniq('vitelib');
|
const viteLib = uniq('vitelib');
|
||||||
|
|||||||
@ -1,11 +1,13 @@
|
|||||||
import {
|
import {
|
||||||
cleanupProject,
|
cleanupProject,
|
||||||
createFile,
|
createFile,
|
||||||
|
killPorts,
|
||||||
listFiles,
|
listFiles,
|
||||||
newProject,
|
newProject,
|
||||||
readFile,
|
readFile,
|
||||||
runCLI,
|
runCLI,
|
||||||
runCLIAsync,
|
runCLIAsync,
|
||||||
|
runE2ETests,
|
||||||
uniq,
|
uniq,
|
||||||
updateFile,
|
updateFile,
|
||||||
} from '@nx/e2e/utils';
|
} from '@nx/e2e/utils';
|
||||||
@ -21,6 +23,26 @@ describe('Build React applications and libraries with Webpack', () => {
|
|||||||
cleanupProject();
|
cleanupProject();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should generate app with custom port', async () => {
|
||||||
|
const appName = uniq('app');
|
||||||
|
const customPort = 8081;
|
||||||
|
|
||||||
|
runCLI(
|
||||||
|
`generate @nx/react:app apps/${appName} --bundler=webpack --port=${customPort} --unitTestRunner=none --no-interactive --e2eTestRunner=playwright`
|
||||||
|
);
|
||||||
|
|
||||||
|
const webpackConfig = readFile(`apps/${appName}/webpack.config.js`);
|
||||||
|
expect(webpackConfig).toContain(`port: ${customPort}`);
|
||||||
|
|
||||||
|
if (runE2ETests()) {
|
||||||
|
const e2eResults = runCLI(`e2e ${appName}-e2e`, {
|
||||||
|
verbose: true,
|
||||||
|
});
|
||||||
|
expect(e2eResults).toContain('Successfully ran target e2e for project');
|
||||||
|
expect(await killPorts()).toBeTruthy();
|
||||||
|
}
|
||||||
|
}, 300_000);
|
||||||
|
|
||||||
// Regression test: https://github.com/nrwl/nx/issues/21773
|
// Regression test: https://github.com/nrwl/nx/issues/21773
|
||||||
it('should support SVGR and SVG asset in the same project', async () => {
|
it('should support SVGR and SVG asset in the same project', async () => {
|
||||||
const appName = uniq('app');
|
const appName = uniq('app');
|
||||||
|
|||||||
@ -1866,4 +1866,291 @@ describe('app', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('--port', () => {
|
||||||
|
it('should generate app with custom port for vite', async () => {
|
||||||
|
await applicationGenerator(appTree, {
|
||||||
|
...schema,
|
||||||
|
directory: 'my-app',
|
||||||
|
bundler: 'vite',
|
||||||
|
port: 9000,
|
||||||
|
});
|
||||||
|
|
||||||
|
const viteConfig = appTree.read('my-app/vite.config.ts', 'utf-8');
|
||||||
|
expect(viteConfig).toMatchInlineSnapshot(`
|
||||||
|
"/// <reference types='vitest' />
|
||||||
|
import { defineConfig } from 'vite';
|
||||||
|
import react from '@vitejs/plugin-react';
|
||||||
|
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
||||||
|
import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
||||||
|
|
||||||
|
export default defineConfig(() => ({
|
||||||
|
root: __dirname,
|
||||||
|
cacheDir: '../node_modules/.vite/my-app',
|
||||||
|
server:{
|
||||||
|
port: 9000,
|
||||||
|
host: 'localhost',
|
||||||
|
},
|
||||||
|
preview:{
|
||||||
|
port: 9000,
|
||||||
|
host: 'localhost',
|
||||||
|
},
|
||||||
|
plugins: [react(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])],
|
||||||
|
// Uncomment this if you are using workers.
|
||||||
|
// worker: {
|
||||||
|
// plugins: [ nxViteTsPaths() ],
|
||||||
|
// },
|
||||||
|
build: {
|
||||||
|
outDir: '../dist/my-app',
|
||||||
|
emptyOutDir: true,
|
||||||
|
reportCompressedSize: true,
|
||||||
|
commonjsOptions: {
|
||||||
|
transformMixedEsModules: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
"
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should generate app with custom port for webpack', async () => {
|
||||||
|
await applicationGenerator(appTree, {
|
||||||
|
...schema,
|
||||||
|
directory: 'my-app',
|
||||||
|
bundler: 'webpack',
|
||||||
|
port: 9000,
|
||||||
|
});
|
||||||
|
|
||||||
|
const webpackConfig = appTree.read('my-app/webpack.config.js', 'utf-8');
|
||||||
|
expect(webpackConfig).toMatchInlineSnapshot(`
|
||||||
|
"const { NxAppWebpackPlugin } = require('@nx/webpack/app-plugin');
|
||||||
|
const { NxReactWebpackPlugin } = require('@nx/react/webpack-plugin');
|
||||||
|
const { join } = require('path');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
output: {
|
||||||
|
path: join(__dirname, '../dist/my-app'),
|
||||||
|
},
|
||||||
|
devServer: {
|
||||||
|
port: 9000,
|
||||||
|
historyApiFallback: {
|
||||||
|
index: '/index.html',
|
||||||
|
disableDotRule: true,
|
||||||
|
htmlAcceptHeaders: ['text/html', 'application/xhtml+xml'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
new NxAppWebpackPlugin({
|
||||||
|
tsConfig: './tsconfig.app.json',
|
||||||
|
compiler: 'babel',
|
||||||
|
main: './src/main.tsx',
|
||||||
|
index: './src/index.html',
|
||||||
|
baseHref: '/',
|
||||||
|
assets: ["./src/favicon.ico","./src/assets"],
|
||||||
|
styles: ["./src/styles.css"],
|
||||||
|
outputHashing: process.env['NODE_ENV'] === 'production' ? 'all' : 'none',
|
||||||
|
optimization: process.env['NODE_ENV'] === 'production',
|
||||||
|
}),
|
||||||
|
new NxReactWebpackPlugin({
|
||||||
|
// Uncomment this line if you don't want to use SVGR
|
||||||
|
// See: https://react-svgr.com/
|
||||||
|
// svgr: false
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
};
|
||||||
|
"
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should generate app with custom port for rspack', async () => {
|
||||||
|
await applicationGenerator(appTree, {
|
||||||
|
...schema,
|
||||||
|
directory: 'my-app',
|
||||||
|
bundler: 'rspack',
|
||||||
|
port: 9000,
|
||||||
|
});
|
||||||
|
|
||||||
|
const rspackConfig = appTree.read('my-app/rspack.config.js', 'utf-8');
|
||||||
|
expect(rspackConfig).toMatchInlineSnapshot(`
|
||||||
|
"const { NxAppRspackPlugin } = require('@nx/rspack/app-plugin');
|
||||||
|
const { NxReactRspackPlugin } = require('@nx/rspack/react-plugin');
|
||||||
|
const { join } = require('path');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
output: {
|
||||||
|
path: join(__dirname, '../dist/my-app'),
|
||||||
|
},
|
||||||
|
devServer: {
|
||||||
|
port: 9000,
|
||||||
|
historyApiFallback: {
|
||||||
|
index: '/index.html',
|
||||||
|
disableDotRule: true,
|
||||||
|
htmlAcceptHeaders: ['text/html', 'application/xhtml+xml'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
new NxAppRspackPlugin({
|
||||||
|
tsConfig: './tsconfig.app.json',
|
||||||
|
main: './src/main.tsx',
|
||||||
|
index: './src/index.html',
|
||||||
|
baseHref: '/',
|
||||||
|
assets: ["./src/favicon.ico","./src/assets"],
|
||||||
|
styles: ["./src/styles.css"],
|
||||||
|
outputHashing: process.env['NODE_ENV'] === 'production' ? 'all' : 'none',
|
||||||
|
optimization: process.env['NODE_ENV'] === 'production',
|
||||||
|
}),
|
||||||
|
new NxReactRspackPlugin({
|
||||||
|
// Uncomment this line if you don't want to use SVGR
|
||||||
|
// See: https://react-svgr.com/
|
||||||
|
// svgr: false
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
};
|
||||||
|
"
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should use default port when not specified', async () => {
|
||||||
|
await applicationGenerator(appTree, {
|
||||||
|
...schema,
|
||||||
|
directory: 'my-app',
|
||||||
|
bundler: 'vite',
|
||||||
|
});
|
||||||
|
|
||||||
|
const viteConfig = appTree.read('my-app/vite.config.ts', 'utf-8');
|
||||||
|
expect(viteConfig).toMatchInlineSnapshot(`
|
||||||
|
"/// <reference types='vitest' />
|
||||||
|
import { defineConfig } from 'vite';
|
||||||
|
import react from '@vitejs/plugin-react';
|
||||||
|
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
||||||
|
import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
||||||
|
|
||||||
|
export default defineConfig(() => ({
|
||||||
|
root: __dirname,
|
||||||
|
cacheDir: '../node_modules/.vite/my-app',
|
||||||
|
server:{
|
||||||
|
port: 4200,
|
||||||
|
host: 'localhost',
|
||||||
|
},
|
||||||
|
preview:{
|
||||||
|
port: 4300,
|
||||||
|
host: 'localhost',
|
||||||
|
},
|
||||||
|
plugins: [react(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])],
|
||||||
|
// Uncomment this if you are using workers.
|
||||||
|
// worker: {
|
||||||
|
// plugins: [ nxViteTsPaths() ],
|
||||||
|
// },
|
||||||
|
build: {
|
||||||
|
outDir: '../dist/my-app',
|
||||||
|
emptyOutDir: true,
|
||||||
|
reportCompressedSize: true,
|
||||||
|
commonjsOptions: {
|
||||||
|
transformMixedEsModules: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
"
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should generate vite app with cypress using custom port', async () => {
|
||||||
|
await applicationGenerator(appTree, {
|
||||||
|
...schema,
|
||||||
|
directory: 'my-app',
|
||||||
|
bundler: 'vite',
|
||||||
|
e2eTestRunner: 'cypress',
|
||||||
|
port: 9000,
|
||||||
|
});
|
||||||
|
|
||||||
|
const cypressConfig = appTree.read(
|
||||||
|
'my-app-e2e/cypress.config.ts',
|
||||||
|
'utf-8'
|
||||||
|
);
|
||||||
|
expect(cypressConfig).toContain("baseUrl: 'http://localhost:9000'");
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should generate vite app with playwright using custom port', async () => {
|
||||||
|
await applicationGenerator(appTree, {
|
||||||
|
...schema,
|
||||||
|
directory: 'my-app',
|
||||||
|
bundler: 'vite',
|
||||||
|
e2eTestRunner: 'playwright',
|
||||||
|
port: 9000,
|
||||||
|
});
|
||||||
|
|
||||||
|
const playwrightConfig = appTree.read(
|
||||||
|
'my-app-e2e/playwright.config.ts',
|
||||||
|
'utf-8'
|
||||||
|
);
|
||||||
|
expect(playwrightConfig).toContain("|| 'http://localhost:9000'");
|
||||||
|
expect(playwrightConfig).toContain("url: 'http://localhost:9000'");
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should generate webpack app with cypress using custom port', async () => {
|
||||||
|
await applicationGenerator(appTree, {
|
||||||
|
...schema,
|
||||||
|
directory: 'my-app',
|
||||||
|
bundler: 'webpack',
|
||||||
|
e2eTestRunner: 'cypress',
|
||||||
|
port: 9000,
|
||||||
|
});
|
||||||
|
|
||||||
|
const cypressConfig = appTree.read(
|
||||||
|
'my-app-e2e/cypress.config.ts',
|
||||||
|
'utf-8'
|
||||||
|
);
|
||||||
|
expect(cypressConfig).toContain("baseUrl: 'http://localhost:9000'");
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should generate webpack app with playwright using custom port', async () => {
|
||||||
|
await applicationGenerator(appTree, {
|
||||||
|
...schema,
|
||||||
|
directory: 'my-app',
|
||||||
|
bundler: 'webpack',
|
||||||
|
e2eTestRunner: 'playwright',
|
||||||
|
port: 9000,
|
||||||
|
});
|
||||||
|
|
||||||
|
const playwrightConfig = appTree.read(
|
||||||
|
'my-app-e2e/playwright.config.ts',
|
||||||
|
'utf-8'
|
||||||
|
);
|
||||||
|
expect(playwrightConfig).toContain("|| 'http://localhost:9000'");
|
||||||
|
expect(playwrightConfig).toContain("url: 'http://localhost:9000'");
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should generate rspack app with cypress using custom port', async () => {
|
||||||
|
await applicationGenerator(appTree, {
|
||||||
|
...schema,
|
||||||
|
directory: 'my-app',
|
||||||
|
bundler: 'rspack',
|
||||||
|
e2eTestRunner: 'cypress',
|
||||||
|
port: 9000,
|
||||||
|
});
|
||||||
|
|
||||||
|
const cypressConfig = appTree.read(
|
||||||
|
'my-app-e2e/cypress.config.ts',
|
||||||
|
'utf-8'
|
||||||
|
);
|
||||||
|
expect(cypressConfig).toContain("baseUrl: 'http://localhost:9000'");
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should generate rspack app with playwright using custom port', async () => {
|
||||||
|
await applicationGenerator(appTree, {
|
||||||
|
...schema,
|
||||||
|
directory: 'my-app',
|
||||||
|
bundler: 'rspack',
|
||||||
|
e2eTestRunner: 'playwright',
|
||||||
|
port: 9000,
|
||||||
|
});
|
||||||
|
|
||||||
|
const playwrightConfig = appTree.read(
|
||||||
|
'my-app-e2e/playwright.config.ts',
|
||||||
|
'utf-8'
|
||||||
|
);
|
||||||
|
expect(playwrightConfig).toContain("|| 'http://localhost:9000'");
|
||||||
|
expect(playwrightConfig).toContain("url: 'http://localhost:9000'");
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -8,7 +8,7 @@ module.exports = {
|
|||||||
path: join(__dirname, '<%= rspackPluginOptions.outputPath %>'),
|
path: join(__dirname, '<%= rspackPluginOptions.outputPath %>'),
|
||||||
},
|
},
|
||||||
devServer: {
|
devServer: {
|
||||||
port: 4200,
|
port: <%= port %>,
|
||||||
historyApiFallback: {
|
historyApiFallback: {
|
||||||
index: '/index.html',
|
index: '/index.html',
|
||||||
disableDotRule: true,
|
disableDotRule: true,
|
||||||
|
|||||||
@ -8,7 +8,7 @@ module.exports = {
|
|||||||
path: join(__dirname, '<%= webpackPluginOptions.outputPath %>'),
|
path: join(__dirname, '<%= webpackPluginOptions.outputPath %>'),
|
||||||
},
|
},
|
||||||
devServer: {
|
devServer: {
|
||||||
port: 4200,
|
port: <%= port %>,
|
||||||
historyApiFallback: {
|
historyApiFallback: {
|
||||||
index: '/index.html',
|
index: '/index.html',
|
||||||
disableDotRule: true,
|
disableDotRule: true,
|
||||||
|
|||||||
@ -37,7 +37,7 @@ export async function addE2e(
|
|||||||
e2eCiWebServerCommand: `${getPackageManagerCommand().exec} nx run ${
|
e2eCiWebServerCommand: `${getPackageManagerCommand().exec} nx run ${
|
||||||
options.projectName
|
options.projectName
|
||||||
}:serve-static`,
|
}:serve-static`,
|
||||||
e2eCiBaseUrl: `http://localhost:4200`,
|
e2eCiBaseUrl: `http://localhost:${options.port ?? 4300}`,
|
||||||
e2eDevServerTarget: `${options.projectName}:serve`,
|
e2eDevServerTarget: `${options.projectName}:serve`,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -81,7 +81,9 @@ export async function addE2e(
|
|||||||
`vite.config.${options.js ? 'js' : 'ts'}`
|
`vite.config.${options.js ? 'js' : 'ts'}`
|
||||||
),
|
),
|
||||||
options.addPlugin,
|
options.addPlugin,
|
||||||
options.devServerPort ?? 4200
|
options.devServerPort ?? 4200,
|
||||||
|
// If the user manually sets the port, then use it for dev and preview
|
||||||
|
options.port
|
||||||
)
|
)
|
||||||
: await getViteE2EWebServerInfo(
|
: await getViteE2EWebServerInfo(
|
||||||
tree,
|
tree,
|
||||||
@ -91,7 +93,9 @@ export async function addE2e(
|
|||||||
`vite.config.${options.js ? 'js' : 'ts'}`
|
`vite.config.${options.js ? 'js' : 'ts'}`
|
||||||
),
|
),
|
||||||
options.addPlugin,
|
options.addPlugin,
|
||||||
options.devServerPort ?? 4200
|
options.devServerPort ?? 4200,
|
||||||
|
// If the user manually sets the port, then use it for dev and preview
|
||||||
|
options.port
|
||||||
);
|
);
|
||||||
} else if (options.bundler === 'rsbuild') {
|
} else if (options.bundler === 'rsbuild') {
|
||||||
ensurePackage('@nx/rsbuild', nxVersion);
|
ensurePackage('@nx/rsbuild', nxVersion);
|
||||||
|
|||||||
@ -42,6 +42,7 @@ export async function setupViteConfiguration(
|
|||||||
skipFormat: true,
|
skipFormat: true,
|
||||||
addPlugin: options.addPlugin,
|
addPlugin: options.addPlugin,
|
||||||
projectType: 'application',
|
projectType: 'application',
|
||||||
|
port: options.port,
|
||||||
});
|
});
|
||||||
tasks.push(viteTask);
|
tasks.push(viteTask);
|
||||||
createOrEditViteConfig(
|
createOrEditViteConfig(
|
||||||
@ -52,6 +53,8 @@ export async function setupViteConfiguration(
|
|||||||
includeVitest: options.unitTestRunner === 'vitest',
|
includeVitest: options.unitTestRunner === 'vitest',
|
||||||
inSourceTests: options.inSourceTests,
|
inSourceTests: options.inSourceTests,
|
||||||
rollupOptionsExternal: ["'react'", "'react-dom'", "'react/jsx-runtime'"],
|
rollupOptionsExternal: ["'react'", "'react-dom'", "'react/jsx-runtime'"],
|
||||||
|
port: options.port,
|
||||||
|
previewPort: options.port,
|
||||||
...(options.useReactRouter
|
...(options.useReactRouter
|
||||||
? reactRouterFrameworkConfig
|
? reactRouterFrameworkConfig
|
||||||
: baseReactConfig),
|
: baseReactConfig),
|
||||||
|
|||||||
@ -57,6 +57,7 @@ export function getDefaultTemplateVariables(
|
|||||||
style: options.style === 'tailwind' ? 'css' : options.style,
|
style: options.style === 'tailwind' ? 'css' : options.style,
|
||||||
hasStyleFile,
|
hasStyleFile,
|
||||||
isUsingTsSolutionSetup: isUsingTsSolutionSetup(host),
|
isUsingTsSolutionSetup: isUsingTsSolutionSetup(host),
|
||||||
|
port: options.port ?? 4200,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -87,7 +87,7 @@ export async function normalizeOptions<T extends Schema = Schema>(
|
|||||||
normalized.unitTestRunner = normalized.unitTestRunner ?? 'jest';
|
normalized.unitTestRunner = normalized.unitTestRunner ?? 'jest';
|
||||||
normalized.e2eTestRunner = normalized.e2eTestRunner ?? 'playwright';
|
normalized.e2eTestRunner = normalized.e2eTestRunner ?? 'playwright';
|
||||||
normalized.inSourceTests = normalized.minimal || normalized.inSourceTests;
|
normalized.inSourceTests = normalized.minimal || normalized.inSourceTests;
|
||||||
normalized.devServerPort ??= findFreePort(host);
|
normalized.devServerPort ??= options.port ?? findFreePort(host);
|
||||||
normalized.minimal = normalized.minimal ?? false;
|
normalized.minimal = normalized.minimal ?? false;
|
||||||
|
|
||||||
return normalized;
|
return normalized;
|
||||||
|
|||||||
@ -33,6 +33,7 @@ export interface Schema {
|
|||||||
useTsSolution?: boolean;
|
useTsSolution?: boolean;
|
||||||
formatter?: 'prettier' | 'none';
|
formatter?: 'prettier' | 'none';
|
||||||
useProjectJson?: boolean;
|
useProjectJson?: boolean;
|
||||||
|
port?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface NormalizedSchema<T extends Schema = Schema> extends T {
|
export interface NormalizedSchema<T extends Schema = Schema> extends T {
|
||||||
|
|||||||
@ -16,6 +16,10 @@
|
|||||||
{
|
{
|
||||||
"command": "nx g app apps/myapp --routing",
|
"command": "nx g app apps/myapp --routing",
|
||||||
"description": "Set up React Router"
|
"description": "Set up React Router"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "nx g app apps/myapp --port=3000",
|
||||||
|
"description": "Set up the dev server to use port 3000"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@ -196,6 +200,12 @@
|
|||||||
"useProjectJson": {
|
"useProjectJson": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Use a `project.json` configuration file instead of inlining the Nx configuration in the `package.json` file."
|
"description": "Use a `project.json` configuration file instead of inlining the Nx configuration in the `package.json` file."
|
||||||
|
},
|
||||||
|
"port": {
|
||||||
|
"type": "number",
|
||||||
|
"description": "The port to use for the development server",
|
||||||
|
"x-prompt": "Which port would you like to use for the dev server?",
|
||||||
|
"default": 4200
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["directory"],
|
"required": ["directory"],
|
||||||
|
|||||||
@ -31,7 +31,7 @@ export async function getRsbuildE2EWebServerInfo(
|
|||||||
defaultServeTargetName: 'dev',
|
defaultServeTargetName: 'dev',
|
||||||
defaultServeStaticTargetName: 'preview',
|
defaultServeStaticTargetName: 'preview',
|
||||||
defaultE2EWebServerAddress: `http://localhost:${e2ePort}`,
|
defaultE2EWebServerAddress: `http://localhost:${e2ePort}`,
|
||||||
defaultE2ECiBaseUrl: 'http://localhost:4200',
|
defaultE2ECiBaseUrl: `http://localhost:${e2ePort}`,
|
||||||
defaultE2EPort: e2ePort,
|
defaultE2EPort: e2ePort,
|
||||||
},
|
},
|
||||||
isPluginBeingAdded
|
isPluginBeingAdded
|
||||||
|
|||||||
@ -33,7 +33,10 @@ describe('@nx/rspack', () => {
|
|||||||
'my-app/project.json',
|
'my-app/project.json',
|
||||||
JSON.stringify({ name: 'my-app' })
|
JSON.stringify({ name: 'my-app' })
|
||||||
);
|
);
|
||||||
tempFs.createFileSync('my-app/rspack.config.ts', `export default {};`);
|
tempFs.createFileSync(
|
||||||
|
'my-app/rspack.config.ts',
|
||||||
|
`export default { devServer: { port: 9000 } };`
|
||||||
|
);
|
||||||
tempFs.createFileSync('package-lock.json', `{}`);
|
tempFs.createFileSync('package-lock.json', `{}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -132,6 +135,7 @@ describe('@nx/rspack', () => {
|
|||||||
"executor": "@nx/web:file-server",
|
"executor": "@nx/web:file-server",
|
||||||
"options": {
|
"options": {
|
||||||
"buildTarget": "build",
|
"buildTarget": "build",
|
||||||
|
"port": 9000,
|
||||||
"spa": true,
|
"spa": true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@ -247,6 +247,12 @@ async function createRspackTargets(
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// for `convert-to-inferred` we need to leave the port undefined or the options will not match
|
||||||
|
if (rspackConfig.devServer?.port && rspackConfig.devServer?.port !== 4200) {
|
||||||
|
targets[options.serveStaticTargetName].options.port =
|
||||||
|
rspackConfig.devServer.port;
|
||||||
|
}
|
||||||
|
|
||||||
if (isTsSolutionSetup) {
|
if (isTsSolutionSetup) {
|
||||||
targets[options.buildTargetName].syncGenerators = [
|
targets[options.buildTargetName].syncGenerators = [
|
||||||
'@nx/js:typescript-sync',
|
'@nx/js:typescript-sync',
|
||||||
|
|||||||
@ -31,7 +31,7 @@ export async function getRspackE2EWebServerInfo(
|
|||||||
defaultServeTargetName: 'serve',
|
defaultServeTargetName: 'serve',
|
||||||
defaultServeStaticTargetName: 'preview',
|
defaultServeStaticTargetName: 'preview',
|
||||||
defaultE2EWebServerAddress: `http://localhost:${e2ePort}`,
|
defaultE2EWebServerAddress: `http://localhost:${e2ePort}`,
|
||||||
defaultE2ECiBaseUrl: 'http://localhost:4200',
|
defaultE2ECiBaseUrl: `http://localhost:${e2ePort}`,
|
||||||
defaultE2EPort: e2ePort,
|
defaultE2EPort: e2ePort,
|
||||||
},
|
},
|
||||||
isPluginBeingAdded
|
isPluginBeingAdded
|
||||||
|
|||||||
@ -152,6 +152,7 @@ export async function viteConfigurationGeneratorInternal(
|
|||||||
: `import react from '@vitejs/plugin-react'`,
|
: `import react from '@vitejs/plugin-react'`,
|
||||||
],
|
],
|
||||||
plugins: ['react()'],
|
plugins: ['react()'],
|
||||||
|
port: schema.port,
|
||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
undefined
|
undefined
|
||||||
|
|||||||
@ -8,7 +8,9 @@ export interface ViteConfigurationGeneratorSchema {
|
|||||||
includeLib?: boolean;
|
includeLib?: boolean;
|
||||||
skipFormat?: boolean;
|
skipFormat?: boolean;
|
||||||
testEnvironment?: 'node' | 'jsdom' | 'happy-dom' | 'edge-runtime' | string;
|
testEnvironment?: 'node' | 'jsdom' | 'happy-dom' | 'edge-runtime' | string;
|
||||||
|
port?: number;
|
||||||
// Internal options
|
// Internal options
|
||||||
addPlugin?: boolean;
|
addPlugin?: boolean;
|
||||||
projectType?: 'application' | 'library';
|
projectType?: 'application' | 'library';
|
||||||
|
previewPort?: number;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -55,6 +55,10 @@
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": ["node", "jsdom", "happy-dom", "edge-runtime"],
|
"enum": ["node", "jsdom", "happy-dom", "edge-runtime"],
|
||||||
"default": "jsdom"
|
"default": "jsdom"
|
||||||
|
},
|
||||||
|
"port": {
|
||||||
|
"type": "number",
|
||||||
|
"description": "The port to use for the development server"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"examplesFile": "../../../docs/configuration-examples.md"
|
"examplesFile": "../../../docs/configuration-examples.md"
|
||||||
|
|||||||
@ -6,7 +6,8 @@ export async function getViteE2EWebServerInfo(
|
|||||||
projectName: string,
|
projectName: string,
|
||||||
configFilePath: string,
|
configFilePath: string,
|
||||||
isPluginBeingAdded: boolean,
|
isPluginBeingAdded: boolean,
|
||||||
e2ePortOverride?: number
|
e2ePortOverride?: number,
|
||||||
|
e2eCIPortOverride?: number
|
||||||
) {
|
) {
|
||||||
const nxJson = readNxJson(tree);
|
const nxJson = readNxJson(tree);
|
||||||
let e2ePort = e2ePortOverride ?? 4200;
|
let e2ePort = e2ePortOverride ?? 4200;
|
||||||
@ -35,7 +36,7 @@ export async function getViteE2EWebServerInfo(
|
|||||||
defaultServeTargetName: 'dev',
|
defaultServeTargetName: 'dev',
|
||||||
defaultServeStaticTargetName: 'preview',
|
defaultServeStaticTargetName: 'preview',
|
||||||
defaultE2EWebServerAddress: `http://localhost:${e2ePort}`,
|
defaultE2EWebServerAddress: `http://localhost:${e2ePort}`,
|
||||||
defaultE2ECiBaseUrl: 'http://localhost:4300',
|
defaultE2ECiBaseUrl: `http://localhost:${e2eCIPortOverride ?? 4300}`,
|
||||||
defaultE2EPort: e2ePort,
|
defaultE2EPort: e2ePort,
|
||||||
},
|
},
|
||||||
isPluginBeingAdded
|
isPluginBeingAdded
|
||||||
@ -47,7 +48,8 @@ export async function getReactRouterE2EWebServerInfo(
|
|||||||
projectName: string,
|
projectName: string,
|
||||||
configFilePath: string,
|
configFilePath: string,
|
||||||
isPluginBeingAdded: boolean,
|
isPluginBeingAdded: boolean,
|
||||||
e2ePortOverride?: number
|
e2ePortOverride?: number,
|
||||||
|
e2eCIPortOverride?: number
|
||||||
) {
|
) {
|
||||||
const e2ePort = e2ePortOverride ?? parseInt(process.env.PORT) ?? 4200;
|
const e2ePort = e2ePortOverride ?? parseInt(process.env.PORT) ?? 4200;
|
||||||
|
|
||||||
@ -64,7 +66,7 @@ export async function getReactRouterE2EWebServerInfo(
|
|||||||
defaultServeTargetName: 'dev',
|
defaultServeTargetName: 'dev',
|
||||||
defaultServeStaticTargetName: 'dev',
|
defaultServeStaticTargetName: 'dev',
|
||||||
defaultE2EWebServerAddress: `http://localhost:${e2ePort}`,
|
defaultE2EWebServerAddress: `http://localhost:${e2ePort}`,
|
||||||
defaultE2ECiBaseUrl: 'http://localhost:4200',
|
defaultE2ECiBaseUrl: `http://localhost:${e2eCIPortOverride ?? 4300}`,
|
||||||
defaultE2EPort: e2ePort,
|
defaultE2EPort: e2ePort,
|
||||||
},
|
},
|
||||||
isPluginBeingAdded
|
isPluginBeingAdded
|
||||||
|
|||||||
@ -378,6 +378,8 @@ export interface ViteConfigFileOptions {
|
|||||||
coverageProvider?: 'v8' | 'istanbul' | 'custom';
|
coverageProvider?: 'v8' | 'istanbul' | 'custom';
|
||||||
setupFile?: string;
|
setupFile?: string;
|
||||||
useEsmExtension?: boolean;
|
useEsmExtension?: boolean;
|
||||||
|
port?: number;
|
||||||
|
previewPort?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createOrEditViteConfig(
|
export function createOrEditViteConfig(
|
||||||
@ -501,7 +503,7 @@ ${
|
|||||||
: options.includeLib
|
: options.includeLib
|
||||||
? ''
|
? ''
|
||||||
: ` server:{
|
: ` server:{
|
||||||
port: 4200,
|
port: ${options.port ?? 4200},
|
||||||
host: 'localhost',
|
host: 'localhost',
|
||||||
},`;
|
},`;
|
||||||
|
|
||||||
@ -510,7 +512,7 @@ ${
|
|||||||
: options.includeLib
|
: options.includeLib
|
||||||
? ''
|
? ''
|
||||||
: ` preview:{
|
: ` preview:{
|
||||||
port: 4300,
|
port: ${options.previewPort ?? 4300},
|
||||||
host: 'localhost',
|
host: 'localhost',
|
||||||
},`;
|
},`;
|
||||||
|
|
||||||
|
|||||||
@ -1,138 +0,0 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
||||||
|
|
||||||
exports[`@nx/webpack/plugin should create nodes 1`] = `
|
|
||||||
[
|
|
||||||
[
|
|
||||||
"my-app/webpack.config.js",
|
|
||||||
{
|
|
||||||
"projects": {
|
|
||||||
"my-app": {
|
|
||||||
"metadata": {},
|
|
||||||
"projectType": "application",
|
|
||||||
"targets": {
|
|
||||||
"build-deps": {
|
|
||||||
"dependsOn": [
|
|
||||||
"^build",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
"build-something": {
|
|
||||||
"cache": true,
|
|
||||||
"command": "webpack-cli build",
|
|
||||||
"dependsOn": [
|
|
||||||
"^build-something",
|
|
||||||
],
|
|
||||||
"inputs": [
|
|
||||||
"production",
|
|
||||||
"^production",
|
|
||||||
{
|
|
||||||
"externalDependencies": [
|
|
||||||
"webpack-cli",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
"metadata": {
|
|
||||||
"description": "Runs Webpack build",
|
|
||||||
"help": {
|
|
||||||
"command": "npx webpack-cli build --help",
|
|
||||||
"example": {
|
|
||||||
"args": [
|
|
||||||
"--profile",
|
|
||||||
],
|
|
||||||
"options": {
|
|
||||||
"json": "stats.json",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"technologies": [
|
|
||||||
"webpack",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
"options": {
|
|
||||||
"args": [
|
|
||||||
"--node-env=production",
|
|
||||||
],
|
|
||||||
"cwd": "my-app",
|
|
||||||
},
|
|
||||||
"outputs": [
|
|
||||||
"{projectRoot}/dist/foo",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
"my-serve": {
|
|
||||||
"command": "webpack-cli serve",
|
|
||||||
"continuous": true,
|
|
||||||
"metadata": {
|
|
||||||
"description": "Starts Webpack dev server",
|
|
||||||
"help": {
|
|
||||||
"command": "npx webpack-cli serve --help",
|
|
||||||
"example": {
|
|
||||||
"options": {
|
|
||||||
"args": [
|
|
||||||
"--client-progress",
|
|
||||||
"--history-api-fallback ",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"technologies": [
|
|
||||||
"webpack",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
"options": {
|
|
||||||
"args": [
|
|
||||||
"--node-env=development",
|
|
||||||
],
|
|
||||||
"cwd": "my-app",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"preview-site": {
|
|
||||||
"command": "webpack-cli serve",
|
|
||||||
"continuous": true,
|
|
||||||
"metadata": {
|
|
||||||
"description": "Starts Webpack dev server in production mode",
|
|
||||||
"help": {
|
|
||||||
"command": "npx webpack-cli serve --help",
|
|
||||||
"example": {
|
|
||||||
"options": {
|
|
||||||
"args": [
|
|
||||||
"--client-progress",
|
|
||||||
"--history-api-fallback ",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"technologies": [
|
|
||||||
"webpack",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
"options": {
|
|
||||||
"args": [
|
|
||||||
"--node-env=production",
|
|
||||||
],
|
|
||||||
"cwd": "my-app",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"serve-static": {
|
|
||||||
"continuous": true,
|
|
||||||
"dependsOn": [
|
|
||||||
"build-something",
|
|
||||||
],
|
|
||||||
"executor": "@nx/web:file-server",
|
|
||||||
"options": {
|
|
||||||
"buildTarget": "build-something",
|
|
||||||
"spa": true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"watch-deps": {
|
|
||||||
"command": "npx nx watch --projects my-app --includeDependentProjects -- npx nx build-deps my-app",
|
|
||||||
"continuous": true,
|
|
||||||
"dependsOn": [
|
|
||||||
"build-deps",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
]
|
|
||||||
`;
|
|
||||||
@ -38,6 +38,9 @@ describe('@nx/webpack/plugin', () => {
|
|||||||
output: {
|
output: {
|
||||||
path: 'dist/foo',
|
path: 'dist/foo',
|
||||||
},
|
},
|
||||||
|
devServer: {
|
||||||
|
port: 9000,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
const nodes = await createNodesFunction(
|
const nodes = await createNodesFunction(
|
||||||
['my-app/webpack.config.js'],
|
['my-app/webpack.config.js'],
|
||||||
@ -50,7 +53,143 @@ describe('@nx/webpack/plugin', () => {
|
|||||||
context
|
context
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(nodes).toMatchSnapshot();
|
expect(nodes).toMatchInlineSnapshot(`
|
||||||
|
[
|
||||||
|
[
|
||||||
|
"my-app/webpack.config.js",
|
||||||
|
{
|
||||||
|
"projects": {
|
||||||
|
"my-app": {
|
||||||
|
"metadata": {},
|
||||||
|
"projectType": "application",
|
||||||
|
"targets": {
|
||||||
|
"build-deps": {
|
||||||
|
"dependsOn": [
|
||||||
|
"^build",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"build-something": {
|
||||||
|
"cache": true,
|
||||||
|
"command": "webpack-cli build",
|
||||||
|
"dependsOn": [
|
||||||
|
"^build-something",
|
||||||
|
],
|
||||||
|
"inputs": [
|
||||||
|
"production",
|
||||||
|
"^production",
|
||||||
|
{
|
||||||
|
"externalDependencies": [
|
||||||
|
"webpack-cli",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"description": "Runs Webpack build",
|
||||||
|
"help": {
|
||||||
|
"command": "npx webpack-cli build --help",
|
||||||
|
"example": {
|
||||||
|
"args": [
|
||||||
|
"--profile",
|
||||||
|
],
|
||||||
|
"options": {
|
||||||
|
"json": "stats.json",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"technologies": [
|
||||||
|
"webpack",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"args": [
|
||||||
|
"--node-env=production",
|
||||||
|
],
|
||||||
|
"cwd": "my-app",
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
"{projectRoot}/dist/foo",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"my-serve": {
|
||||||
|
"command": "webpack-cli serve",
|
||||||
|
"continuous": true,
|
||||||
|
"metadata": {
|
||||||
|
"description": "Starts Webpack dev server",
|
||||||
|
"help": {
|
||||||
|
"command": "npx webpack-cli serve --help",
|
||||||
|
"example": {
|
||||||
|
"options": {
|
||||||
|
"args": [
|
||||||
|
"--client-progress",
|
||||||
|
"--history-api-fallback ",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"technologies": [
|
||||||
|
"webpack",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"args": [
|
||||||
|
"--node-env=development",
|
||||||
|
],
|
||||||
|
"cwd": "my-app",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"preview-site": {
|
||||||
|
"command": "webpack-cli serve",
|
||||||
|
"continuous": true,
|
||||||
|
"metadata": {
|
||||||
|
"description": "Starts Webpack dev server in production mode",
|
||||||
|
"help": {
|
||||||
|
"command": "npx webpack-cli serve --help",
|
||||||
|
"example": {
|
||||||
|
"options": {
|
||||||
|
"args": [
|
||||||
|
"--client-progress",
|
||||||
|
"--history-api-fallback ",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"technologies": [
|
||||||
|
"webpack",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"args": [
|
||||||
|
"--node-env=production",
|
||||||
|
],
|
||||||
|
"cwd": "my-app",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"serve-static": {
|
||||||
|
"continuous": true,
|
||||||
|
"dependsOn": [
|
||||||
|
"build-something",
|
||||||
|
],
|
||||||
|
"executor": "@nx/web:file-server",
|
||||||
|
"options": {
|
||||||
|
"buildTarget": "build-something",
|
||||||
|
"port": 9000,
|
||||||
|
"spa": true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"watch-deps": {
|
||||||
|
"command": "npx nx watch --projects my-app --includeDependentProjects -- npx nx build-deps my-app",
|
||||||
|
"continuous": true,
|
||||||
|
"dependsOn": [
|
||||||
|
"build-deps",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
]
|
||||||
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
function mockWebpackConfig(config: any) {
|
function mockWebpackConfig(config: any) {
|
||||||
|
|||||||
@ -268,6 +268,12 @@ async function createWebpackTargets(
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// for `convert-to-inferred` we need to leave the port undefined or the options will not match
|
||||||
|
if (webpackConfig.devServer?.port && webpackConfig.devServer?.port !== 4200) {
|
||||||
|
targets[options.serveStaticTargetName].options.port =
|
||||||
|
webpackConfig.devServer.port;
|
||||||
|
}
|
||||||
|
|
||||||
if (isTsSolutionSetup) {
|
if (isTsSolutionSetup) {
|
||||||
targets[options.buildTargetName].syncGenerators = [
|
targets[options.buildTargetName].syncGenerators = [
|
||||||
'@nx/js:typescript-sync',
|
'@nx/js:typescript-sync',
|
||||||
|
|||||||
@ -31,7 +31,7 @@ export async function getWebpackE2EWebServerInfo(
|
|||||||
defaultServeTargetName: 'serve',
|
defaultServeTargetName: 'serve',
|
||||||
defaultServeStaticTargetName: 'serve-static',
|
defaultServeStaticTargetName: 'serve-static',
|
||||||
defaultE2EWebServerAddress: `http://localhost:${e2ePort}`,
|
defaultE2EWebServerAddress: `http://localhost:${e2ePort}`,
|
||||||
defaultE2ECiBaseUrl: 'http://localhost:4200',
|
defaultE2ECiBaseUrl: `http://localhost:${e2ePort}`,
|
||||||
defaultE2EPort: e2ePort,
|
defaultE2EPort: e2ePort,
|
||||||
},
|
},
|
||||||
isPluginBeingAdded
|
isPluginBeingAdded
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user