Skip to content
This repository has been archived by the owner on Aug 7, 2021. It is now read-only.

Commit

Permalink
Merge pull request #1103 from NativeScript/tachev/fix-angular-scoped-…
Browse files Browse the repository at this point in the history
…packages

fix: avoid duplicate modules from tns-core-modules and @nativescript/core
  • Loading branch information
rosen-vladimirov authored Dec 4, 2019
2 parents 9358e83 + 2fe4928 commit e4bc3c5
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 19 deletions.
18 changes: 14 additions & 4 deletions demo/AngularApp/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const { nsReplaceBootstrap } = require("nativescript-dev-webpack/transformers/ns
const { nsReplaceLazyLoader } = require("nativescript-dev-webpack/transformers/ns-replace-lazy-loader");
const { nsSupportHmrNg } = require("nativescript-dev-webpack/transformers/ns-support-hmr-ng");
const { getMainModulePath } = require("nativescript-dev-webpack/utils/ast-utils");
const { getNoEmitOnErrorFromTSConfig } = require("nativescript-dev-webpack/utils/tsconfig-utils");
const { getNoEmitOnErrorFromTSConfig, getCompilerOptionsFromTSConfig } = require("nativescript-dev-webpack/utils/tsconfig-utils");
const CleanWebpackPlugin = require("clean-webpack-plugin");
const CopyWebpackPlugin = require("copy-webpack-plugin");
const { BundleAnalyzerPlugin } = require("webpack-bundle-analyzer");
Expand Down Expand Up @@ -61,19 +61,28 @@ module.exports = env => {
const isAnySourceMapEnabled = !!sourceMap || !!hiddenSourceMap;
const externals = nsWebpack.getConvertedExternals(env.externals);
const appFullPath = resolve(projectRoot, appPath);
const tsConfigName = "tsconfig.tns.json";
const tsConfigPath = join(__dirname, tsConfigName);
const hasRootLevelScopedModules = nsWebpack.hasRootLevelScopedModules({ projectDir: projectRoot });
const hasRootLevelScopedAngular = nsWebpack.hasRootLevelScopedAngular({ projectDir: projectRoot });
let coreModulesPackageName = "tns-core-modules";
const alias = {
'~': appFullPath
};

const compilerOptions = getCompilerOptionsFromTSConfig(tsConfigPath);
if (hasRootLevelScopedModules) {
coreModulesPackageName = "@nativescript/core";
alias["tns-core-modules"] = coreModulesPackageName;
nsWebpack.processTsPathsForScopedModules({ compilerOptions });
}

if (hasRootLevelScopedAngular) {
alias["nativescript-angular"] = "@nativescript/angular";
nsWebpack.processTsPathsForScopedAngular({ compilerOptions });
}

const appResourcesFullPath = resolve(projectRoot, appResourcesPath);
const tsConfigName = "tsconfig.tns.json";
const entryModule = `${nsWebpack.getEntryModule(appFullPath, platform)}.ts`;
const entryPath = `.${sep}${entryModule}`;
const entries = { bundle: entryPath, application: "./application.android" };
Expand Down Expand Up @@ -110,10 +119,11 @@ module.exports = env => {
hostReplacementPaths: nsWebpack.getResolver([platform, "tns"]),
platformTransformers: ngCompilerTransformers.map(t => t(() => ngCompilerPlugin, resolve(appFullPath, entryModule), projectRoot)),
mainPath: join(appFullPath, entryModule),
tsConfigPath: join(__dirname, tsConfigName),
tsConfigPath,
skipCodeGeneration: !aot,
sourceMap: !!isAnySourceMapEnabled,
additionalLazyModuleResources: additionalLazyModuleResources
additionalLazyModuleResources: additionalLazyModuleResources,
compilerOptions: { paths: compilerOptions.paths }
});

let sourceMapFilename = nsWebpack.getSourceMapFilename(hiddenSourceMap, __dirname, dist);
Expand Down
58 changes: 49 additions & 9 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,28 @@ const {
Object.assign(exports, require("./plugins"));
Object.assign(exports, require("./host/resolver"));

exports.processTsPathsForScopedModules = function ({ compilerOptions }) {
return replacePathInCompilerOptions({
compilerOptions,
targetPath: "tns-core-modules",
replacementPath: "@nativescript/core"
});
}

exports.processTsPathsForScopedAngular = function ({ compilerOptions }) {
return replacePathInCompilerOptions({
compilerOptions,
targetPath: "nativescript-angular",
replacementPath: "@nativescript/angular"
});
}

exports.hasRootLevelScopedModules = function ({ projectDir }) {
let hasRootLevelScopedModules;
try {
const scopedModulesPackageName = '@nativescript/core';
require.resolve(scopedModulesPackageName, { paths: [projectDir] });
hasRootLevelScopedModules = true;
} catch (e) {
hasRootLevelScopedModules = false;
}
return hasRootLevelPackage({ projectDir, packageName: "@nativescript/core" });
}

return hasRootLevelScopedModules;
exports.hasRootLevelScopedAngular = function ({ projectDir }) {
return hasRootLevelPackage({ projectDir, packageName: "@nativescript/angular" });
}

exports.getAotEntryModule = function (appDirectory) {
Expand Down Expand Up @@ -176,3 +187,32 @@ function verifyEntryModuleDirectory(appDirectory) {
throw new Error(`The specified path to app directory ${appDirectory} does not exist. Unable to find entry module.`);
}
}


function hasRootLevelPackage({ projectDir, packageName }) {
let hasRootLevelPackage;
try {
require.resolve(packageName, { paths: [projectDir] });
hasRootLevelPackage = true;
} catch (e) {
hasRootLevelPackage = false;
}

return hasRootLevelPackage;
}

function replacePathInCompilerOptions({ compilerOptions, targetPath, replacementPath }) {
const paths = (compilerOptions && compilerOptions.paths) || {};
for (const key in paths) {
if (paths.hasOwnProperty(key)) {
const pathsForPattern = paths[key];
if (Array.isArray(pathsForPattern)) {
for (let i = 0; i < pathsForPattern.length; ++i) {
if (typeof pathsForPattern[i] === "string") {
pathsForPattern[i] = pathsForPattern[i].replace(targetPath, replacementPath);
}
}
}
}
}
}
18 changes: 14 additions & 4 deletions templates/webpack.angular.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const { nsReplaceBootstrap } = require("nativescript-dev-webpack/transformers/ns
const { nsReplaceLazyLoader } = require("nativescript-dev-webpack/transformers/ns-replace-lazy-loader");
const { nsSupportHmrNg } = require("nativescript-dev-webpack/transformers/ns-support-hmr-ng");
const { getMainModulePath } = require("nativescript-dev-webpack/utils/ast-utils");
const { getNoEmitOnErrorFromTSConfig } = require("nativescript-dev-webpack/utils/tsconfig-utils");
const { getNoEmitOnErrorFromTSConfig, getCompilerOptionsFromTSConfig } = require("nativescript-dev-webpack/utils/tsconfig-utils");
const CleanWebpackPlugin = require("clean-webpack-plugin");
const CopyWebpackPlugin = require("copy-webpack-plugin");
const { BundleAnalyzerPlugin } = require("webpack-bundle-analyzer");
Expand Down Expand Up @@ -60,19 +60,28 @@ module.exports = env => {
const isAnySourceMapEnabled = !!sourceMap || !!hiddenSourceMap;
const externals = nsWebpack.getConvertedExternals(env.externals);
const appFullPath = resolve(projectRoot, appPath);
const tsConfigName = "tsconfig.tns.json";
const tsConfigPath = join(__dirname, tsConfigName);
const hasRootLevelScopedModules = nsWebpack.hasRootLevelScopedModules({ projectDir: projectRoot });
const hasRootLevelScopedAngular = nsWebpack.hasRootLevelScopedAngular({ projectDir: projectRoot });
let coreModulesPackageName = "tns-core-modules";
const alias = {
'~': appFullPath
};

const compilerOptions = getCompilerOptionsFromTSConfig(tsConfigPath);
if (hasRootLevelScopedModules) {
coreModulesPackageName = "@nativescript/core";
alias["tns-core-modules"] = coreModulesPackageName;
nsWebpack.processTsPathsForScopedModules({ compilerOptions });
}

if (hasRootLevelScopedAngular) {
alias["nativescript-angular"] = "@nativescript/angular";
nsWebpack.processTsPathsForScopedAngular({ compilerOptions });
}

const appResourcesFullPath = resolve(projectRoot, appResourcesPath);
const tsConfigName = "tsconfig.tns.json";
const entryModule = `${nsWebpack.getEntryModule(appFullPath, platform)}.ts`;
const entryPath = `.${sep}${entryModule}`;
const entries = { bundle: entryPath };
Expand Down Expand Up @@ -109,10 +118,11 @@ module.exports = env => {
hostReplacementPaths: nsWebpack.getResolver([platform, "tns"]),
platformTransformers: ngCompilerTransformers.map(t => t(() => ngCompilerPlugin, resolve(appFullPath, entryModule), projectRoot)),
mainPath: join(appFullPath, entryModule),
tsConfigPath: join(__dirname, tsConfigName),
tsConfigPath,
skipCodeGeneration: !aot,
sourceMap: !!isAnySourceMapEnabled,
additionalLazyModuleResources: additionalLazyModuleResources
additionalLazyModuleResources: additionalLazyModuleResources,
compilerOptions: { paths: compilerOptions.paths }
});

let sourceMapFilename = nsWebpack.getSourceMapFilename(hiddenSourceMap, __dirname, dist);
Expand Down
9 changes: 7 additions & 2 deletions templates/webpack.config.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ const nativeScriptDevWebpack = {
getAppPath: () => 'app',
getEntryModule: () => 'EntryModule',
hasRootLevelScopedModules: () => false,
hasRootLevelScopedAngular: () => false,
processTsPathsForScopedModules: () => false,
processTsPathsForScopedAngular: () => false,
getResolver: () => null,
getConvertedExternals: nsWebpackIndex.getConvertedExternals,
getSourceMapFilename: nsWebpackIndex.getSourceMapFilename,
Expand All @@ -48,7 +51,7 @@ const webpackConfigAngular = proxyquire('./webpack.angular', {
'nativescript-dev-webpack/transformers/ns-replace-lazy-loader': { nsReplaceLazyLoader: () => { return FakeLazyTransformerFlag } },
'nativescript-dev-webpack/transformers/ns-support-hmr-ng': { nsSupportHmrNg: () => { return FakeHmrTransformerFlag } },
'nativescript-dev-webpack/utils/ast-utils': { getMainModulePath: () => { return "fakePath"; } },
'nativescript-dev-webpack/utils/tsconfig-utils': { getNoEmitOnErrorFromTSConfig: () => { return false; } },
'nativescript-dev-webpack/utils/tsconfig-utils': { getNoEmitOnErrorFromTSConfig: () => { return false; }, getCompilerOptionsFromTSConfig: () => { return false; } },
'nativescript-dev-webpack/plugins/NativeScriptAngularCompilerPlugin': { getAngularCompilerPlugin: () => { return AngularCompilerStub; } },
'@ngtools/webpack': {
AngularCompilerPlugin: AngularCompilerStub
Expand All @@ -59,7 +62,7 @@ const webpackConfigAngular = proxyquire('./webpack.angular', {
const webpackConfigTypeScript = proxyquire('./webpack.typescript', {
'nativescript-dev-webpack': nativeScriptDevWebpack,
'nativescript-dev-webpack/nativescript-target': emptyObject,
'nativescript-dev-webpack/utils/tsconfig-utils': { getNoEmitOnErrorFromTSConfig: () => { return false; } },
'nativescript-dev-webpack/utils/tsconfig-utils': { getNoEmitOnErrorFromTSConfig: () => { return false; }, getCompilerOptionsFromTSConfig: () => { return false; } },
'terser-webpack-plugin': TerserJsStub
});

Expand Down Expand Up @@ -362,6 +365,7 @@ describe('webpack.config.js', () => {
describe(`alias for webpack.${type}.js (${platform})`, () => {
it('should add alias when @nativescript/core is at the root of node_modules', () => {
nativeScriptDevWebpack.hasRootLevelScopedModules = () => true;
nativeScriptDevWebpack.hasRootLevelScopedAngular = () => true;
const input = getInput({ platform });
const config = webpackConfig(input);
expect(config.resolve.alias['tns-core-modules']).toBe('@nativescript/core');
Expand All @@ -371,6 +375,7 @@ describe('webpack.config.js', () => {
});
it('shouldn\'t add alias when @nativescript/core is not at the root of node_modules', () => {
nativeScriptDevWebpack.hasRootLevelScopedModules = () => false;
nativeScriptDevWebpack.hasRootLevelScopedAngular = () => false;
const input = getInput({ platform });
const config = webpackConfig(input);
expect(config.resolve.alias['tns-core-modules']).toBeUndefined();
Expand Down

0 comments on commit e4bc3c5

Please sign in to comment.