Skip to content

Add project source dir as a module #1465

Closed

Description

@filipesilva

It would be very useful to be able to address components via a relative path starting at the project root. A way to do this is to consider the project root as a special project, as if it was inside of node_modules as far as resolution is concerned.

Such a design greatly reinforces the 'app as a library' idea, and plays nice with most module loading scheme.

A proposed name is @app but configurable via angular-cli.json, where app is the project prefix specified in ng new --prefix app (this exists already and defaults to app).

Example:

// instead of 
import { something } from '../../../../../../../shared/something';
// we could do
import { something } from '@app/shared/something';

This would also work for CSS preprocessors.

Such implementation would address #865 and also greatly reduce the need for #900.

Activity

  1. sirajc commented on Jul 28, 2016

    @sirajc

    Have seen similar thing in ng-bootstrap. The demo project inside refers to the main project using @ng-bootstrap and it is using webpack

  2. TheLarkInn commented on Jul 28, 2016

    @TheLarkInn
    Member

    In terms of webpack implementation would we be taking this @app property and mapping them to the webpack alias for module resolution @filipesilva

  3. filipesilva commented on Jul 28, 2016

    @filipesilva
    ContributorAuthor

    Something important that came up: editor tooling would never be able to find @app. You'd always have errors on your editor.

  4. clydin commented on Jul 28, 2016

    @clydin
    Member

    There are also tsconfig's baseUrl and paths options. This would only apply to typescript files but allows editors (e.g., vscode) to process and follow the mapping.

    To make the current version of vscode pick up the settings, you'll need to add a workspace settings file with "typescript.tsdk": "./node_modules/typescript/lib" (make sure it points to your actual typescript location).

        "baseUrl": ".",
        "paths": {
          "@app/*": ["app/*"]
        }
    

    UPDATE:

    The above additions to tsconfig and the inclusion of the TsConfigPathsPlugin in the CLI's web pack config work well so far. It definitely simplifies and improves readability of typescript imports.

  5. masaanli commented on Aug 6, 2016

    @masaanli

    Can't wait on this one :) Also struggling with FontAwesome Fonts implementation. Did a CDN for now...

  6. added
    P5The team acknowledges the request but does not plan to address it, it remains open for discussion
    on Aug 15, 2016
  7. chapati23 commented on Aug 18, 2016

    @chapati23

    Another thing to be aware of with aliases is tests. Just because webpack knows @app as an Ali's doesn't mean mocha or karma etc. will know how to resolve it

  8. ggranum commented on Sep 5, 2016

    @ggranum

    I have basically @rolandoldengarm's issue, but there's a case that might be worth testing for someone: npm link.

    When I attempted anything using symbolic links it seemed that webpack would resolve the real path instead of the alias. Combined with 'tsconfig:paths' not working yet, I cannot fathom solution to 'develop using modules' that's supportable long term.

    Mostly want to call this out because at the moment this is listed as 'nice to have', and I really can't imagine being able to use the tool in this state long term.

    I tried npm link, obviously. But also a few direct symbolic links - the craziest failure was when I symbolically linked a module that depends on another. Consider B depends on A: With both A and B npm install'd, everything works fine. However, removing the install of B and instead creating a symbolic link so that it looks like the source is under the 'app' directory, (and modifying the app.module.ts accordingly) fails, because it can't find module A.

    On the chance this might be of interest to someone here I added some scripts to my repos to help demo it. If not interested, no worries.

    The repositories I'm working on are https://github.com/ggranum/revector and https://github.com/ggranum/revector-demo

    Specifically, if you clone both of those into the same parent and run

    npm install
    ng serve
    

    Everything should work. Now stop the server and run:

     ./symlink-email-module.sh 
    ng serve
    

    and you should reproduce the errors I'm seeing [though note that the sed command in the bash scripts may break on non-macs] :

    ERROR in ../revector/src/lib/email-password-top-nav-login/top-nav-login.component.ts
    Module not found: Error: Can't resolve '@revector/auth-service' in '/Users/ggranum/github/ggranum/revector/src/lib/email-password-top-nav-login'
     @ ../revector/src/lib/email-password-top-nav-login/top-nav-login.component.ts 12:0-68
     @ ../revector/src/lib/email-password-top-nav-login/email-password-top-nav-login.module.ts
     @ ../revector/src/lib/email-password-top-nav-login/index.ts
     @ ./src/app/app.module.ts
     @ ./src/app/index.ts
     @ ./src/main.ts
     @ multi main

    There's a bash script to create npm links as well (but run the uninstall-revector.sh script first).

    If nothing else, hopefully this post serves to point out how hard it will be to write modular code in external projects without this feature.

    Thanks much

  9. ggranum commented on Sep 6, 2016

    @ggranum

    @rolandoldengarm I am now deeply curious: what do you mean when you referenced system-config? Are you using system-config in combination with the webpack version of the CLI? If so, I'd love to hear more...

    As for symlinks... this is unquestionably a design failure of Node. I have a few horrible, evil ideas about how to make the ' --preserve-symlinks' flag propagate through Node's call chain, but nothing I'd be proud of. And certainly nothing that would 'just work' when I clone my repository onto another machine, for example. It might be possible that there is something relatively simple the CLI team could do to enable symlink'd directories to work properly with node/webpack... but a) I doubt it and b) why bother? Leveraging tsconfig:paths just makes so much more sense.

  10. 31 remaining items

  11. Zeioth commented on Aug 21, 2017

    @Zeioth

    I don't get how something so simple can be so hard to achieve.

    Fortunately this guide worked for me.

    In tsconfig.json

    "compilerOptions": {
        "outDir": "./dist/out-tsc",
        "baseUrl": "."
    }

    in webpack.config.js

    module.exports = {
      "resolve": {
        "extensions": [
          ".ts",
          ".js"
        ],
        "modules": [
          "./node_modules",
          ".",
        ]
    }

    Now let's imagine you have the next project structue.

    /** 
     * Assuming the following project structure
     *   /src
     *     /app
     *       /services/file1.js
     *       /models/file2.js
     *     /node_modules
     *     .webpack.config.js
     *     tsconfig.json
     */
    

    If you wanna import the file example 2 from example1, from now on you can use

    import { AnythingIWant} from 'src/app/models/file2';
    
  12. atte-backman commented on Oct 9, 2017

    @atte-backman
    "compilerOptions": {
        "baseUrl": ".",
        "paths": {
            "app": [
                "src/app/*"
            ]
        },
        "include": ["src/**/*"],
        "exclude": []
    }
    

    ... and it should be all good.

  13. ppozniak commented on Oct 13, 2017

    @ppozniak

    Here's how I handled it:
    in tsconfig.json

    "compilerOptions": {
        "baseUrl": "src",
        "paths": {
          "@directives/*": ["app/shared/directives/*"],
          "@services/*": ["app/shared/services/*"],
          "@models/*": ["app/shared/models/*"],
          "@assets/*": ["assets*"],
          "@components/*": ["app/components/*"]
        },
    ...
    

    Example:
    import { ShoppingItem } from "@models/shopping-item.model";

  14. darkbasic commented on Oct 17, 2017

    @darkbasic

    They removed the above mentioned solution with awesome-typescript-loader and they're now using AotPlugin: f9a7c01#diff-3c07f218821da114292666210f358440

    If I use something like import { AppComponent } from 'app/app.component' in app.module.ts then tooling doesn't work and editor complains about TS2307: Cannot find module 'app/app.component'.

    If I put

        "baseUrl": ".",
        "paths": {
          "app/*": ["./src/app/*"]
        },
    

    into tsconfig.json

    then the editor reports an error inside app.component.ts:

    Angular: Component 'AppComponent' is not included in a module and will not be available inside a template. Consider adding it to an NgModule declaration.
    
  15. darkbasic commented on Oct 17, 2017

    @darkbasic

    @abner @filipesilva does the new AotPlugin solution work for you?

    Is it possible to reopen this issue?
    I also tried to eject the config and use Webpack's alias but it didn't work either.

  16. jongunter commented on Oct 19, 2017

    @jongunter

    Seems to work for me if all 3 (app, spec and the one in the root of the project for my IDE) of my tsconfig files have the following lines so they use the @app alias:

    "compilerOptions": {
        "paths": {
          "@app/*": [ "app/*" ]
        }
      }
    
  17. darkbasic commented on Oct 20, 2017

    @darkbasic

    Inside app.component.ts the editor still reports:

    Angular: Component 'AppComponent' is not included in a module and will not be available inside a template. Consider adding it to an NgModule declaration.
    

    Try to use something like import { AppComponent } from 'app/app.component' in app.module.ts.

  18. tihomir-kit commented on Nov 8, 2017

    @tihomir-kit

    For me this worked fine (tsconfig.json, not tsconfig.app.json):

        "baseUrl": "./",
        "paths": {
          "~/*": [ "*" ],
          "@app/*": [ "src/app/*" ],
          "@core/*": [ "src/app/core/*" ],
          "@shared/*": [ "src/app/shared/*" ],
          "@feature/*": [ "src/app/feature/*" ]
        }

    the critical part that I was missing at the beginning was * at the end of both keys and relative paths.

    VIsual Studio recognized the aliases after I restarted it.

  19. Xapuu commented on Dec 7, 2017

    @Xapuu

    Here is my solution

    
    {
      "compileOnSave": false,
      "compilerOptions": {
        "baseUrl": "src",
        "paths": {
          "@models": [
            "./app/models/index.ts"
          ],
          "@environment": [
            "./environments/environment.ts"
          ],
          "@services/*": [
            "./app/services/*"
          ]
        }
      }
    }
    

    Be aware that you must restart the CLI each time you make any changes in the tsconfig.json, so that they can take effect, also be aware that although the routes will work, you probably wont have any autocomplete for them.

  20. sergey-morenets commented on Jan 10, 2018

    @sergey-morenets

    Works for me this way (in tsconfig.json only):

    "paths": {
          "@domain/*": [
            "./app/domain/*"
          ]
        }
    
    

    And import it:

    import {User} from '@domain/User';

  21. otaviodecampos commented on Feb 7, 2018

    @otaviodecampos

    @Xapuu worked for me too. thanks

  22. nweldev commented on Apr 19, 2018

    @nweldev
    Contributor

    @clydin / @filipesilva How do you think we should handle this in a CLI v6 project with libraries ? Especially when following angular/devkit#730 (comment).

  23. stephaneeybert commented on Jul 15, 2019

    @stephaneeybert

    For a library type project, how to have these paths mappings seen by a client application ?

  24. angular-automatic-lock-bot commented on Sep 9, 2019

    @angular-automatic-lock-bot

    This issue has been automatically locked due to inactivity.
    Please file a new issue if you are encountering a similar or related problem.

    Read more about our automatic conversation locking policy.

    This action has been performed automatically by a bot.

  25. locked and limited conversation to collaborators on Sep 9, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P5The team acknowledges the request but does not plan to address it, it remains open for discussionfeatureLabel used to distinguish feature request from other issues

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions