Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 2 bundle like import / Import multiple modules

I didn't know how to state the question... So, basically I'm writing my own application using Angular 2 with Typescript. I would like to make it possible to import my modules the way we do with Angular, where we can import multiple related modules in one line. For example, we could do this in angular2 beta:

import { Component, OnInit, Input } from 'angular2/core';

I would like to do something similar with my app. For example:

import { UserService, RoleService } from 'my-project/services';

Also, I want to be able to do the same for models, pipes, components, etc...

One more thing, the folder structure would be something like this:

src/app/services
src/app/components
src/app/models
src/app/pipes

What I tried to do: On path src/app, I created on file for each 'bundle', like services.d.ts, models.d.ts, pipes.d.ts... And then I tried to map on SystemJS config, like so:

(function(global) {

  // map tells the System loader where to look for things
  var map = {
    'app':                        'src/app', // 'dist',
    'rxjs':                       'node_modules/rxjs',
      'my-project/components':                  'src/app/components',
      'my-project/services':                'src/app/services',
      'my-project/models':                        'src/app/models',
      'my-project/pipes':                           'src/app/pipes',
    '@angular':                   'node_modules/@angular'
  };

  // packages tells the System loader how to load when no filename and/or no extension
  var packages = {
    'app':                        { format: 'register', main: 'main.js',  defaultExtension: 'js' },
    'rxjs':                       { defaultExtension: 'js' },
  };

  var packageNames = [
    'my-project/components',
    'my-project/services',
    'my-project/models',
    'my-project/pipes',
    '@angular/common',
    '@angular/compiler',
    '@angular/core',
    '@angular/http',
    '@angular/platform-browser',
    '@angular/platform-browser-dynamic',
    '@angular/router-deprecated',
    '@angular/testing',
    '@angular/upgrade',
  ];

  // add package entries for angular packages in the form '@angular/common': { main: 'index.js', defaultExtension: 'js' }
  packageNames.forEach(function(pkgName) {
    packages[pkgName] = { main: 'index.js', defaultExtension: 'js' };
  });

  var config = {
    map: map,
    packages: packages
  };

  System.config(config);

})(this);

The problem is Visual Studio Code doesn't recognize the imports in my .ts files. It says it couldn't find the module.

like image 201
digaomatias Avatar asked May 17 '16 22:05

digaomatias


2 Answers

You need 2 things to accomplish this. First, as other answer pointed out, you need to create "barrels" (index.ts) inside src/app/services, src/app/models and other such folders. So you folder structure looks something like this:

enter image description here

Where the index.ts files contain the exports of stuff that you want to import in your application:

export * from './service1';
export * from './service2';

So far, this will give you the possibility to do this:

import { Service1, Service2 } from '../../services';

However, this is not ideal because of the relative paths like ../../. In order to fix this, you need do one more step: specify baseUrl and paths TypeScript options in tsconfig.json (see https://www.typescriptlang.org/docs/handbook/module-resolution.html).

If you only want to get rid of relative paths, you just need to specify the baseUrl option like this:

tsconfig.json:

{
  "compilerOptions": {
    ...
    "baseUrl": "./src"
  }
}

After this is done, you should be able to import your services like this:

import { Service1, Service2 } from 'app/services';

But if you also need to have import like my-project/services (my-project instead of app), then you also need to specify paths configuration like the following:

{
  "compilerOptions": {
    ...
    "baseUrl": "./src",
    "paths": {
      "my-project/*": [
        "app/*"
      ]      
    }
  }
}

With this configuration the following should work:

import { Service1, Service2 } from 'my-project/services';
like image 180
Pavlo Glazkov Avatar answered Oct 25 '22 00:10

Pavlo Glazkov


You'll want to create a barrel inside the services folder (for example) which will export all nested exports manually, this way you can import 2 (or more) modules from the barrel, where before you'd have to use 2 different imports.

Last I heard, this breaks tree-shaking for some reason, but I might wrong about this.

Anyway, read up some more here.

like image 41
Amit Avatar answered Oct 25 '22 01:10

Amit