UNPKG

@nx/webpack

Version:

The Nx Plugin for Webpack contains executors and generators that support building applications using Webpack.

176 lines (175 loc) • 8.87 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.normalizeOptions = normalizeOptions; exports.normalizeAssets = normalizeAssets; exports.normalizeFileReplacements = normalizeFileReplacements; const path_1 = require("path"); const fs_1 = require("fs"); const devkit_1 = require("@nx/devkit"); function normalizeOptions(options) { const combinedPluginAndMaybeExecutorOptions = {}; const isProd = process.env.NODE_ENV === 'production'; // Since this is invoked by the executor, the graph has already been created and cached. const projectGraph = (0, devkit_1.readCachedProjectGraph)(); const taskDetailsFromBuildTarget = process.env.NX_BUILD_TARGET ? (0, devkit_1.parseTargetString)(process.env.NX_BUILD_TARGET, projectGraph) : undefined; const projectName = taskDetailsFromBuildTarget ? taskDetailsFromBuildTarget.project : process.env.NX_TASK_TARGET_PROJECT; const targetName = taskDetailsFromBuildTarget ? taskDetailsFromBuildTarget.target : process.env.NX_TASK_TARGET_TARGET; const configurationName = taskDetailsFromBuildTarget ? taskDetailsFromBuildTarget.configuration : process.env.NX_TASK_TARGET_CONFIGURATION; const projectNode = projectGraph.nodes[projectName]; const targetConfig = projectNode.data.targets[targetName]; normalizeRelativePaths(projectNode.data.root, options); // Merge options from `@nx/webpack:webpack` into plugin options. // Options from `@nx/webpack:webpack` take precedence. const originalTargetOptions = targetConfig.options; if (configurationName) { Object.assign(originalTargetOptions, targetConfig.configurations?.[configurationName]); } // This could be called from dev-server which means we need to read `buildTarget` to get actual build options. // Otherwise, the options are passed from the `@nx/webpack:webpack` executor. if (originalTargetOptions.buildTarget) { const buildTargetOptions = targetConfig.options; if (configurationName) { Object.assign(buildTargetOptions, targetConfig.configurations?.[configurationName]); } Object.assign(combinedPluginAndMaybeExecutorOptions, options, // executor options take precedence (especially for overriding with CLI args) buildTargetOptions); } else { Object.assign(combinedPluginAndMaybeExecutorOptions, options, // executor options take precedence (especially for overriding with CLI args) originalTargetOptions); } const sourceRoot = projectNode.data.sourceRoot ?? ((0, fs_1.existsSync)((0, path_1.join)(devkit_1.workspaceRoot, projectNode.data.root, 'src')) ? (0, path_1.join)(projectNode.data.root, 'src') : projectNode.data.root); if (!combinedPluginAndMaybeExecutorOptions.main) { throw new Error(`Missing "main" option for the entry file. Set this option in your Nx webpack plugin.`); } return { ...combinedPluginAndMaybeExecutorOptions, assets: combinedPluginAndMaybeExecutorOptions.assets ? normalizeAssets(combinedPluginAndMaybeExecutorOptions.assets, devkit_1.workspaceRoot, sourceRoot, projectNode.data.root) : [], baseHref: combinedPluginAndMaybeExecutorOptions.baseHref ?? '/', buildLibsFromSource: combinedPluginAndMaybeExecutorOptions.buildLibsFromSource ?? true, commonChunk: combinedPluginAndMaybeExecutorOptions.commonChunk ?? true, compiler: combinedPluginAndMaybeExecutorOptions.compiler ?? 'babel', configurationName, deleteOutputPath: combinedPluginAndMaybeExecutorOptions.deleteOutputPath ?? true, extractCss: combinedPluginAndMaybeExecutorOptions.extractCss ?? true, fileReplacements: normalizeFileReplacements(devkit_1.workspaceRoot, combinedPluginAndMaybeExecutorOptions.fileReplacements), generateIndexHtml: combinedPluginAndMaybeExecutorOptions.generateIndexHtml ?? true, main: combinedPluginAndMaybeExecutorOptions.main, namedChunks: combinedPluginAndMaybeExecutorOptions.namedChunks ?? !isProd, optimization: combinedPluginAndMaybeExecutorOptions.optimization ?? isProd, outputFileName: combinedPluginAndMaybeExecutorOptions.outputFileName ?? 'main.js', outputHashing: combinedPluginAndMaybeExecutorOptions.outputHashing ?? (isProd ? 'all' : 'none'), outputPath: combinedPluginAndMaybeExecutorOptions.outputPath, projectGraph, projectName, projectRoot: projectNode.data.root, root: devkit_1.workspaceRoot, runtimeChunk: combinedPluginAndMaybeExecutorOptions.runtimeChunk ?? true, scripts: combinedPluginAndMaybeExecutorOptions.scripts ?? [], sourceMap: combinedPluginAndMaybeExecutorOptions.sourceMap ?? !isProd, sourceRoot, styles: combinedPluginAndMaybeExecutorOptions.styles ?? [], target: combinedPluginAndMaybeExecutorOptions.target, targetName, vendorChunk: combinedPluginAndMaybeExecutorOptions.vendorChunk ?? !isProd, sassImplementation: combinedPluginAndMaybeExecutorOptions.sassImplementation ?? 'sass', }; } function normalizeAssets(assets, root, sourceRoot, projectRoot, resolveRelativePathsToProjectRoot = true) { return assets.map((asset) => { if (typeof asset === 'string') { const assetPath = (0, devkit_1.normalizePath)(asset); const resolvedAssetPath = (0, path_1.resolve)(root, assetPath); const resolvedSourceRoot = (0, path_1.resolve)(root, sourceRoot); if (!resolvedAssetPath.startsWith(resolvedSourceRoot)) { throw new Error(`The ${resolvedAssetPath} asset path must start with the project source root: ${sourceRoot}`); } const isDirectory = (0, fs_1.statSync)(resolvedAssetPath).isDirectory(); const input = isDirectory ? resolvedAssetPath : (0, path_1.dirname)(resolvedAssetPath); const output = (0, path_1.relative)(resolvedSourceRoot, (0, path_1.resolve)(root, input)); const glob = isDirectory ? '**/*' : (0, path_1.basename)(resolvedAssetPath); return { input, output, glob, }; } else { if (asset.output.startsWith('..')) { throw new Error('An asset cannot be written to a location outside of the output path.'); } const assetPath = (0, devkit_1.normalizePath)(asset.input); let resolvedAssetPath = (0, path_1.resolve)(root, assetPath); if (resolveRelativePathsToProjectRoot && asset.input.startsWith('.')) { const resolvedProjectRoot = (0, path_1.resolve)(root, projectRoot); resolvedAssetPath = (0, path_1.resolve)(resolvedProjectRoot, assetPath); } return { ...asset, input: resolvedAssetPath, // Now we remove starting slash to make Webpack place it from the output root. output: asset.output.replace(/^\//, ''), }; } }); } function normalizeFileReplacements(root, fileReplacements) { return fileReplacements ? fileReplacements.map((fileReplacement) => ({ replace: (0, path_1.resolve)(root, fileReplacement.replace), with: (0, path_1.resolve)(root, fileReplacement.with), })) : []; } function normalizeRelativePaths(projectRoot, options) { for (const [fieldName, fieldValue] of Object.entries(options)) { if (isRelativePath(fieldValue)) { options[fieldName] = (0, path_1.join)(projectRoot, fieldValue); } else if (fieldName === 'additionalEntryPoints') { for (let i = 0; i < fieldValue.length; i++) { const v = fieldValue[i]; if (isRelativePath(v)) { fieldValue[i] = { entryName: (0, path_1.parse)(v).name, entryPath: (0, path_1.join)(projectRoot, v), }; } else if (isRelativePath(v.entryPath)) { v.entryPath = (0, path_1.join)(projectRoot, v.entryPath); } } } else if (Array.isArray(fieldValue)) { for (let i = 0; i < fieldValue.length; i++) { if (isRelativePath(fieldValue[i])) { fieldValue[i] = (0, path_1.join)(projectRoot, fieldValue[i]); } } } } } function isRelativePath(val) { return (typeof val === 'string' && (val.startsWith('./') || // Windows val.startsWith('.\\'))); }