diff --git a/bin/commands/generator/workspace/index.js b/bin/commands/generator/workspace/index.js index de9c04f..bcec746 100644 --- a/bin/commands/generator/workspace/index.js +++ b/bin/commands/generator/workspace/index.js @@ -148,7 +148,6 @@ class Generator extends BasePhoveaGenerator { cwd: this.destinationPath(), }); const plugins = files.map(path.dirname); - const repoDependencies = Object.assign({}, ...plugins.map((plugin) => ({ [plugin]: `link:./${plugin}` }))); const integrateMulti = (target, source) => { Object.keys(source || {}).forEach((key) => { @@ -166,12 +165,17 @@ class Generator extends BasePhoveaGenerator { const devDependencies = {}; const overrides = {}; const scripts = {}; + const pluginToName = {}; + const repoDependencies = {}; plugins.forEach((p) => { const pkg = this.fs.readJSON(this.destinationPath(`${p}/package.json`)); integrateMulti(dependencies, pkg.dependencies); integrateMulti(devDependencies, pkg.devDependencies); integrateMulti(overrides, pkg.overrides); + pluginToName[p] = pkg.name; + repoDependencies[pkg.name] = `link:./${p}`; + // no pre post test tasks Object.keys(pkg.scripts) .filter((s) => !/^(pre|post).*/g.test(s)) @@ -233,6 +237,7 @@ class Generator extends BasePhoveaGenerator { return { plugins, + pluginToName, dependencies: Object.assign(Object.assign(dependencies, extraDependencies), this.options.addWorkspaceRepos ? repoDependencies : {}), devDependencies: Object.assign(devDependencies, extraDevDependencies), overrides: Object.assign(overrides, extraOverrides), @@ -460,7 +465,7 @@ class Generator extends BasePhoveaGenerator { writing() { const { - plugins, dependencies, devDependencies, overrides, resolutions, scripts, + plugins, pluginToName, dependencies, devDependencies, overrides, resolutions, scripts, } = this._generateWebDependencies(); const sdeps = this._generateServerDependencies(); const dockerWebHint = ' # Uncomment the following lines for testing the web production build\n' @@ -495,7 +500,7 @@ class Generator extends BasePhoveaGenerator { const config = {}; config.workspace = path.basename(this.destinationPath()); config.modules = _.union(plugins, sdeps.plugins); - config.webmodules = plugins.filter((d) => fs.existsSync(this.destinationPath(`${d}/src/phovea_registry.ts`))); + config.webmodules = plugins.filter((d) => fs.existsSync(this.destinationPath(`${d}/src/phovea_registry.ts`))).map((d) => pluginToName[d]); config.servermodules = sdeps.plugins; config.dockerCompose = path.resolve(this.destinationPath('docker-compose.yml')); config.wsName = this.options.wsName; diff --git a/config/jest.config.template.js b/config/jest.config.template.js index 87ba124..b4c926f 100644 --- a/config/jest.config.template.js +++ b/config/jest.config.template.js @@ -44,6 +44,6 @@ module.exports = { }, }, moduleNameMapper: { - '^.+\\.(css|less|scss|sass|png|jpg|gif|html)$': 'identity-obj-proxy', + '^.+\\.(css|less|scss|sass|png|jpg|gif|svg|html)$': 'identity-obj-proxy', }, }; diff --git a/config/webpack.config.js b/config/webpack.config.js index 56add1a..bf68629 100644 --- a/config/webpack.config.js +++ b/config/webpack.config.js @@ -1,3 +1,5 @@ +/* eslint-disable global-require */ +/* eslint-disable import/no-dynamic-require */ const path = require('path'); const fs = require('fs'); const webpack = require('webpack'); @@ -49,9 +51,7 @@ module.exports = (env, argv) => { vendors: any; devServerProxy: any; } */ - // eslint-disable-next-line global-require,import/no-dynamic-require const workspaceYoRcFile = fs.existsSync(path.join(workspacePath, '.yo-rc-workspace.json')) ? require(path.join(workspacePath, '.yo-rc-workspace.json')) : {}; - // eslint-disable-next-line global-require,import/no-dynamic-require const workspacePkg = require(path.join(workspacePath, 'package.json')); const workspaceBuildInfoFile = path.join(workspacePath, 'package-lock.json'); const workspaceMetaDataFile = path.join(workspacePath, 'metaData.json'); @@ -61,10 +61,15 @@ module.exports = (env, argv) => { const workspaceProxy = workspaceYoRcFile.devServerProxy || {}; const workspaceRepos = isSingleRepoMode ? ['./'] : workspaceYoRcFile.frontendRepos || []; const workspaceMaxChunkSize = workspaceYoRcFile.maxChunkSize || 5000000; + const resolveAliases = Object.fromEntries(Object.entries(workspaceYoRcFile.resolveAliases || {}).map(([key, p]) => [key, path.join(workspacePath, p)])); + // Use a regex with capturing group as explained in https://github.com/webpack/webpack/pull/14509#issuecomment-1237348087. + const customResolveAliasRegex = Object.entries(resolveAliases).length > 0 ? new RegExp(`/^(.+?[\\/]node_modules[\\/](?!(${Object.keys(resolveAliases).join('|')}))(@.+?[\\/])?.+?)[\\/]/`) : null; + Object.entries(resolveAliases).forEach(([key, p]) => console.log(`Using custom resolve alias: ${key} -> ${p}`)); + + const workspaceRepoToName = Object.fromEntries(workspaceRepos.map((r) => [r, require(path.join(workspacePath, r, 'package.json')).name])); const defaultApp = isSingleRepoMode ? './' : workspaceYoRcFile.defaultApp; const defaultAppPath = path.join(workspacePath, defaultApp); - // eslint-disable-next-line global-require,import/no-dynamic-require const appPkg = require(path.join(defaultAppPath, 'package.json')); const libName = appPkg.name; const libDesc = appPkg.description; @@ -362,22 +367,32 @@ module.exports = (env, argv) => { // new CssMinimizerPlugin(), ], }, + snapshot: { + managedPaths: customResolveAliasRegex ? [ + customResolveAliasRegex, + ] : undefined, + }, resolve: { extensions: ['.tsx', '.ts', '.js'], + // By default, always search for modules in the relative node_modules. However, + // if the package can not be found, fall back to the workspace node_modules. This is + // useful when using the resolveAliases to resolve a package to somewhere else. + modules: ['node_modules', path.join(workspacePath, 'node_modules')], alias: Object.assign( { // Alias to jsx-runtime required as only React@18 has this export, otherwise it fails with "The request 'react/jsx-runtime' failed to resolve only because it was resolved as fully specified". // See https://github.com/facebook/react/issues/20235 for details. 'react/jsx-runtime': 'react/jsx-runtime.js', 'react/jsx-dev-runtime': 'react/jsx-dev-runtime.js', + ...resolveAliases, }, // Add aliases for all the workspace repos ...(!isSingleRepoMode ? workspaceRepos.map((repo) => ({ // Rewrite all '/dist' imports to '/src' - [`${repo}/dist`]: path.join(workspacePath, repo, 'src'), - [`${repo}/src`]: path.join(workspacePath, repo, 'src'), - [`${repo}`]: path.join(workspacePath, repo, 'src'), + [`${workspaceRepoToName[repo]}/dist`]: path.join(workspacePath, repo, 'src'), + [`${workspaceRepoToName[repo]}/src`]: path.join(workspacePath, repo, 'src'), + [`${workspaceRepoToName[repo]}`]: path.join(workspacePath, repo, 'src'), })) : [ { @@ -398,7 +413,7 @@ module.exports = (env, argv) => { // Handle node_modules packages that contain sourcemaps shouldUseSourceMap && { enforce: 'pre', - exclude: /@babel(?:\/|\\{1,2})runtime/, + exclude: [/@babel(?:\/|\\{1,2})runtime/, customResolveAliasRegex].filter(Boolean), test: /\.(js|mjs|jsx|ts|tsx|css)$/, loader: require.resolve('source-map-loader'), }, @@ -444,7 +459,7 @@ module.exports = (env, argv) => { // The preset includes JSX, Flow, TypeScript, and some ESnext features. { test: /\.(js|mjs|jsx|ts|tsx)$/, - exclude: /node_modules/, + exclude: [/node_modules/, customResolveAliasRegex].filter(Boolean), loader: 'babel-loader', options: { presets: [['@babel/preset-env', { targets: { browsers: 'last 2 Chrome versions' } }], '@babel/preset-typescript', '@babel/preset-react'], @@ -688,10 +703,11 @@ module.exports = (env, argv) => { incremental: true, paths: Object.assign( {}, + resolveAliases, ...(!isSingleRepoMode ? workspaceRepos.map((r) => ({ - [`${r}/dist`]: [path.join(workspacePath, r, 'src/*')], - [r]: [path.join(workspacePath, r, 'src/index.ts')], + [`${workspaceRepoToName[r]}/dist`]: [path.join(workspacePath, r, 'src/*')], + [workspaceRepoToName[r]]: [path.join(workspacePath, r, 'src/index.ts')], })) : [ { diff --git a/package.json b/package.json index 269f68e..7d0a15e 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "visyn_scripts", "description": "", - "version": "1.0.1", + "version": "1.1.0", "author": { "name": "datavisyn GmbH", "email": "contact@datavisyn.io",