Skip to content

Conversation

@vakrilov
Copy link
Contributor

@vakrilov vakrilov commented Feb 27, 2019

The Problem

Imports for Web or Mobile-specific files cause errors in IDEs and build time.

Example:

  • You have service that has platform-specific implementations for web and mobile in service.tns.ts and service.web.ts.
  • The service is imported in another module with import { xxx } from ".../service"
  • IDE (ex. VsCode) will (rightfully) complain that it cannot find the service module

The Solution

Configure typescript to resolve platform-specific files (with .tns.ts/.web.ts extension) with priority over shared files (just *.ts). The configuration is done by setting paths in tsconfig. Here is how the tsconfig.tns.json (used for mobile) looks:

"compilerOptions": { //... "paths": { "@src/*": [ "src/*.android.ts", "src/*.ios.ts", "src/*.tns.ts", "src/*" ] } } 

Important Remarks

  1. The common config contains mappings for both web and mobile so that paths can work and be resolved inside IDE (ex. VS Code) while developing.
  2. Platform-specific configs contain mapping only for the platform (see example above).
  3. We map @src/ to the src folder of the project. Other symbols can be used - like @proj/. However, don’t use “~/" - this leads to confusing build-time errors and suffering. The reason: “~/" is reserved and is already used as an alias in webpack configuration it is needed for CSS files resolution.
  4. The “paths” mapping only work for non-relative imports. This means that all imports that should be resolved to a plat-specific file should be defined with as non-relative paths starting with @src. Our suggestion is to adopt a convention to use @src for all project files imports and enforce it with a tslint rule.
  5. Sometimes when building for NativeScript there is a problem with the AOT compiler picking up “*.ts” extension that is intended for web-only. It then fails with a component/module not used error. To solve that we explicitly specify files in tns and web ts-configurations. These are the entry points to TS compilations. All lazy modules should be specified in “files” list in tsconfigs, as they are not directly imported in other TS files.

Tasks

  • Modify ng-new schematic to create apps using the ts-configuration described above.
  • Create a tslint rule that enforces non-relative imports. It should have an auto-fix option that replaces relative imports with the @src scheme
  • There are a couple of places in schematics that we need to resolve imports. Resolve them using the ts-configurations so that they can work with @src and basePath mappings
  • Make sure all schematics work and produce code with @src imports (instead of relative). We can just reuse the tslint rule. We can execute the rule with --fix to make it fix relative imports that we have generated
    • ng-new
    • add-ns
    • shared
    • generate component
    • generate module
    • master-detail template
    • migrate-module
    • migrate-component
  • Update the documentation

Fixes #172

@cla-bot cla-bot bot added the cla: yes label Feb 27, 2019
@vakrilov vakrilov force-pushed the shared-structure branch from 3849f72 to 9fd675e Compare May 16, 2019 12:37
@vakrilov vakrilov marked this pull request as ready for review May 29, 2019 08:44
@vakrilov vakrilov requested a review from sebawita May 29, 2019 08:47
]
}
},
"files": [
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the purpose of adding main.ts and polyfills.ts explicitly?

When I manually migrated this project: https://github.com/sebawita/angular-getting-started
Steps:

  1. update angular.json - add -> "cli": { "defaultCollection": "@nativescript/schematics" }
  2. run ng g ng-add - make sure the this uses the schematics from the PR
  3. ng serve -o

I get this error:

Refused to load the image 'http://localhost:4200/favicon.ico' because it violates the following Content Security Policy directive: "default-src 'none'". Note that 'img-src' was not explicitly set, so 'default-src' is used as a fallback. 

This can be fixed either by:
a) Changing the files to src/main.ts and src/polyfills.ts
b) removing the files array

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch! The file paths are relative to the src directory.
In Angular 7.0 the tsconfig.app.json file is in my-project/src. That's why the paths are main.ts and polyfills.ts. However, in Angular 8.0, the tsconfig.app.json file is on root level - in ./my-project. The paths should be changed to src/main.ts and src/polyfills.ts.
This problem will be addressed in the PR, upgrading to Angular 8.0.

@sis0k0
Copy link
Contributor

sis0k0 commented Jun 19, 2019

test

@sis0k0 sis0k0 merged commit 7c3d159 into master Jun 19, 2019
@sis0k0 sis0k0 deleted the shared-structure branch June 19, 2019 07:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

4 participants