252 lines
6.9 KiB
TypeScript
252 lines
6.9 KiB
TypeScript
import {
|
|
formatFiles,
|
|
GeneratorCallback,
|
|
joinPathFragments,
|
|
offsetFromRoot,
|
|
readNxJson,
|
|
readProjectConfiguration,
|
|
runTasksInSerial,
|
|
Tree,
|
|
updateProjectConfiguration,
|
|
writeJson,
|
|
} from '@nx/devkit';
|
|
|
|
import { webpackInitGenerator } from '../init/init';
|
|
import { ConfigurationGeneratorSchema } from './schema';
|
|
import { WebpackExecutorOptions } from '../../executors/webpack/schema';
|
|
import { hasPlugin } from '../../utils/has-plugin';
|
|
import { addBuildTargetDefaults } from '@nx/devkit/src/generators/add-build-target-defaults';
|
|
import { ensureDependencies } from '../../utils/ensure-dependencies';
|
|
|
|
export function configurationGenerator(
|
|
tree: Tree,
|
|
options: ConfigurationGeneratorSchema
|
|
) {
|
|
return configurationGeneratorInternal(tree, { addPlugin: false, ...options });
|
|
}
|
|
|
|
export async function configurationGeneratorInternal(
|
|
tree: Tree,
|
|
options: ConfigurationGeneratorSchema
|
|
) {
|
|
const tasks: GeneratorCallback[] = [];
|
|
const nxJson = readNxJson(tree);
|
|
const addPluginDefault =
|
|
process.env.NX_ADD_PLUGINS !== 'false' &&
|
|
nxJson.useInferencePlugins !== false;
|
|
options.addPlugin ??= addPluginDefault;
|
|
|
|
const initTask = await webpackInitGenerator(tree, {
|
|
...options,
|
|
skipFormat: true,
|
|
});
|
|
tasks.push(initTask);
|
|
|
|
const depsTask = ensureDependencies(tree, {
|
|
compiler: options.compiler === 'babel' ? undefined : options.compiler,
|
|
});
|
|
tasks.push(depsTask);
|
|
|
|
checkForTargetConflicts(tree, options);
|
|
|
|
if (!hasPlugin(tree)) {
|
|
addBuildTarget(tree, options);
|
|
if (options.devServer) {
|
|
addServeTarget(tree, options);
|
|
}
|
|
}
|
|
|
|
createWebpackConfig(tree, options);
|
|
|
|
if (!options.skipFormat) {
|
|
await formatFiles(tree);
|
|
}
|
|
|
|
return runTasksInSerial(...tasks);
|
|
}
|
|
|
|
function checkForTargetConflicts(
|
|
tree: Tree,
|
|
options: ConfigurationGeneratorSchema
|
|
) {
|
|
if (options.skipValidation) return;
|
|
|
|
const project = readProjectConfiguration(tree, options.project);
|
|
|
|
if (project.targets?.build) {
|
|
throw new Error(
|
|
`Project "${project.name}" already has a build target. Pass --skipValidation to ignore this error.`
|
|
);
|
|
}
|
|
|
|
if (options.devServer && project.targets?.serve) {
|
|
throw new Error(
|
|
`Project "${project.name}" already has a serve target. Pass --skipValidation to ignore this error.`
|
|
);
|
|
}
|
|
}
|
|
|
|
function createWebpackConfig(
|
|
tree: Tree,
|
|
options: ConfigurationGeneratorSchema
|
|
) {
|
|
const project = readProjectConfiguration(tree, options.project);
|
|
const buildOptions: WebpackExecutorOptions = {
|
|
target: options.target,
|
|
outputPath: joinPathFragments('dist', project.root),
|
|
compiler: options.compiler ?? 'swc',
|
|
main: options.main ?? joinPathFragments(project.root, 'src/main.ts'),
|
|
tsConfig:
|
|
options.tsConfig ?? joinPathFragments(project.root, 'tsconfig.app.json'),
|
|
webpackConfig: joinPathFragments(project.root, 'webpack.config.js'),
|
|
};
|
|
|
|
if (options.target === 'web') {
|
|
tree.write(
|
|
joinPathFragments(project.root, 'webpack.config.js'),
|
|
hasPlugin(tree)
|
|
? `
|
|
const { NxAppWebpackPlugin } = require('@nx/webpack/app-plugin');
|
|
const { join } = require('path');
|
|
|
|
module.exports = {
|
|
output: {
|
|
path: join(__dirname, '${offsetFromRoot(project.root)}${
|
|
buildOptions.outputPath
|
|
}'),
|
|
},
|
|
plugins: [
|
|
new NxAppWebpackPlugin({
|
|
target: '${buildOptions.target}',
|
|
tsConfig: '${buildOptions.tsConfig}',
|
|
compiler: '${buildOptions.compiler}',
|
|
main: '${buildOptions.main}',
|
|
outputHashing: '${buildOptions.target !== 'web' ? 'none' : 'all'}',
|
|
})
|
|
],
|
|
}
|
|
`
|
|
: `
|
|
const { composePlugins, withNx, withWeb } = require('@nx/webpack');
|
|
|
|
// Nx plugins for webpack.
|
|
module.exports = composePlugins(withNx(), withWeb(), (config) => {
|
|
// Update the webpack config as needed here.
|
|
// e.g. \`config.plugins.push(new MyPlugin())\`
|
|
return config;
|
|
});
|
|
`
|
|
);
|
|
} else {
|
|
tree.write(
|
|
joinPathFragments(project.root, 'webpack.config.js'),
|
|
hasPlugin(tree)
|
|
? `
|
|
const { NxAppWebpackPlugin } = require('@nx/webpack/app-plugin');
|
|
const { join } = require('path');
|
|
|
|
module.exports = {
|
|
output: {
|
|
path: join(__dirname, '${offsetFromRoot(project.root)}${
|
|
buildOptions.outputPath
|
|
}'),
|
|
},
|
|
plugins: [
|
|
new NxAppWebpackPlugin({
|
|
target: '${buildOptions.target}',
|
|
tsConfig: '${buildOptions.tsConfig}',
|
|
compiler: '${buildOptions.compiler}',
|
|
main: '${buildOptions.main}',
|
|
outputHashing: '${buildOptions.target !== 'web' ? 'none' : 'all'}',
|
|
})
|
|
],
|
|
}
|
|
`
|
|
: `
|
|
const { composePlugins, withNx } = require('@nx/webpack');
|
|
|
|
// Nx plugins for webpack.
|
|
module.exports = composePlugins(withNx(), (config) => {
|
|
// Update the webpack config as needed here.
|
|
// e.g. \`config.plugins.push(new MyPlugin())\`
|
|
return config;
|
|
});
|
|
`
|
|
);
|
|
}
|
|
}
|
|
|
|
function addBuildTarget(tree: Tree, options: ConfigurationGeneratorSchema) {
|
|
addBuildTargetDefaults(tree, '@nx/webpack:webpack');
|
|
|
|
const project = readProjectConfiguration(tree, options.project);
|
|
const buildOptions: WebpackExecutorOptions = {
|
|
target: options.target,
|
|
outputPath: joinPathFragments('dist', project.root),
|
|
compiler: options.compiler ?? 'swc',
|
|
main: options.main ?? joinPathFragments(project.root, 'src/main.ts'),
|
|
tsConfig:
|
|
options.tsConfig ?? joinPathFragments(project.root, 'tsconfig.app.json'),
|
|
webpackConfig: joinPathFragments(project.root, 'webpack.config.js'),
|
|
};
|
|
|
|
if (options.webpackConfig) {
|
|
buildOptions.webpackConfig = options.webpackConfig;
|
|
}
|
|
|
|
if (options.babelConfig) {
|
|
buildOptions.babelConfig = options.babelConfig;
|
|
} else if (options.compiler === 'babel') {
|
|
// If no babel config file is provided then write a default one, otherwise build will fail.
|
|
writeJson(tree, joinPathFragments(project.root, '.babelrc'), {
|
|
presets: ['@nx/js/babel'],
|
|
});
|
|
}
|
|
|
|
updateProjectConfiguration(tree, options.project, {
|
|
...project,
|
|
targets: {
|
|
...project.targets,
|
|
build: {
|
|
executor: '@nx/webpack:webpack',
|
|
outputs: ['{options.outputPath}'],
|
|
defaultConfiguration: 'production',
|
|
options: buildOptions,
|
|
configurations: {
|
|
production: {
|
|
optimization: true,
|
|
outputHashing: options.target === 'web' ? 'all' : 'none',
|
|
sourceMap: false,
|
|
namedChunks: false,
|
|
extractLicenses: true,
|
|
vendorChunk: false,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
});
|
|
}
|
|
|
|
function addServeTarget(tree: Tree, options: ConfigurationGeneratorSchema) {
|
|
const project = readProjectConfiguration(tree, options.project);
|
|
updateProjectConfiguration(tree, options.project, {
|
|
...project,
|
|
targets: {
|
|
...project.targets,
|
|
serve: {
|
|
executor: '@nx/webpack:dev-server',
|
|
options: {
|
|
buildTarget: `${options.project}:build`,
|
|
},
|
|
configurations: {
|
|
production: {
|
|
buildTarget: `${options.project}:build:production`,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
});
|
|
}
|
|
|
|
export default configurationGenerator;
|