Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
392 views
in Technique[技术] by (71.8m points)

javascript - How to import a barrel by folder name only?

Angular 2 Barrels

In Angular 2, I'm trying to get barrels to work as described in the documentation.

The official Angular 2 style guide talks about using barrels to aggregate and shorten import statements.

I'm finding out that for some barrels, I have to specify the index JavaScript file name on the import when I shouldn't have to.

Barrel Example

(modify the app/app.component.ts file on line 12)

After have encountered this in my actual project (running under ASP.NET) I have created a Plunker to demonstrate the problem where I modified the Tour of Heroes to use barrels.

In app/app.component, the basic way to import is like this:

import { HeroService } from './hero.service';
import { HeroesComponent } from './heroes.component';
import { HeroDetailComponent } from './hero-detail.component';

But, to use a barrel instead, the import definition would look like this:

import {
  HeroService,
  HeroesComponent,
  HeroDetailComponent
} from '../app';

The from '../app'; line indicates a file with the name of index.ts that contain the exported/imported components:

// app/index.ts
export * from './hero-detail.component';
export * from './hero.service';
export * from './heroes.component';

But this doesn't work for me in all cases. The only way I've gotten this to work correctly is by explicitly including the index file name:

import {
  HeroService,
  HeroesComponent,
  HeroDetailComponent
} from '../app/index'; // have to indicate 'index'

How can I get this to work where the index.js file name is implied?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

AFAIK SystemJS doesn't understand barrels by itself but Webpack does. BTW, After digging up how Angular does it for it's modules, I've found a solution


In system.config.js you'll need to do the following things

Note: the parent directory of a index.ts is the barrel, ICYDK

  • Add the paths of your barrels

// map tells the System loader where to look for things
  var map = {
    'app':                        'app', // 'dist',
    'rxjs':                       'node_modules/rxjs',
    'angular2-in-memory-web-api': 'node_modules/angular2-in-memory-web-api',
    '@angular':                   'node_modules/@angular',

    'barrel':                 'path/to/your/barrel'
  };
  • Don't add barrels to packages (explained later)##

// packages tells the System loader how to load when no filename and/or no extension
  var packages = {
    'app':                        { main: 'app/boot.js',  defaultExtension: 'js' },
    'rxjs':                       { defaultExtension: 'js' },
    'angular2-in-memory-web-api': { defaultExtension: 'js' }
  };
  • Add them to packageNames, just like angular

var packageNames = [
    '@angular/common',
    ...
    '@angular/upgrade',

    'barrel'
  ];

And you're done.


##

Why we used packageNames instead of packages is because you'll have to repeat the { main: 'index.js', defaultExtension: 'js' } (filename and extension) for every barrel, but angular is already doing it by looping with this.

packageNames.forEach(function(pkgName) {
    packages[pkgName] = { main: 'index.js', defaultExtension: 'js' };
});

Which is ultimately adding them to packages.


Usage

import {something} from '../../barrel'; // relative path to directory of barrel

and

import {something} from 'barrel'; // name of barrel

Both work, but the later one fails to provide intellisense and shows an error saying cannot find module 'barrel'. Which I don't have a solution for. But I'll add it when I do.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...