简体   繁体   English

Angular 2 bundle就像导入/导入多个模块一样

[英]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. 我不知道如何陈述问题......所以,基本上我正在使用带有Typescript的Angular 2编写我自己的应用程序。 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. 我希望能够像我们使用Angular一样导入模块,我们可以在一行中导入多个相关模块。 For example, we could do this in angular2 beta: 例如,我们可以在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 /应用/服务
src/app/components SRC /应用/组件
src/app/models SRC /应用/型号
src/app/pipes SRC /应用程序/管

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: 我试图做的事情:在路径src / app上,我在文件中创建了每个'bundle',比如services.d.ts,models.d.ts,pipes.d.ts ......然后我试着映射SystemJS配置,如下所示:

(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. 问题是Visual Studio Code无法识别我的.ts文件中的导入。 It says it couldn't find the module. 它说无法找到模块。

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. 首先,正如其他答案所指出的,您需要在src/app/servicessrc/app/models和其他此类文件夹中创建“桶”( index.ts )。 So you folder structure looks something like this: 所以你的文件夹结构看起来像这样:

在此输入图像描述

Where the index.ts files contain the exports of stuff that you want to import in your application: index.ts文件包含要在应用程序中导入的东西的导出:

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 ). 为了解决这个问题,你需要做的一个步骤:指定baseUrlpaths在打字稿选项tsconfig.json (见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: 如果你只想摆脱相对路径,你只需要像这样指定baseUrl选项:

tsconfig.json: 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: 但是如果您还需要像my-project/servicesmy-project而不是app )那样导入,那么您还需要指定paths配置,如下所示:

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

With this configuration the following should work: 使用此配置,以下应该有效:

import { Service1, Service2 } from 'my-project/services';

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. 你需要在services文件夹中创建一个桶(例如),它将手动导出所有嵌套导出,这样你就可以从桶中导入2个(或更多)模块,之后你必须使用2个不同的导入。

Last I heard, this breaks tree-shaking for some reason, but I might wrong about this. 最后我听说,由于某种原因,这会打破树木震动,但我可能会对此不以为然。

Anyway, read up some more here . 无论如何,请在这里阅读更多内容。

Edit: closer to what you want 编辑:更接近你想要的

You could generate the declaration files of your app and add them to the @types folder (or create your own and add that to the tsconfig's typeRoots array). 您可以生成应用程序的声明文件并将它们添加到@types文件夹(或创建自己的文件夹并将其添加到tsconfig的typeRoots数组中)。

New tsconfig 新的tsconfig

You could use the console but I would recommend creating a new tsconfig_decl.json file. 您可以使用控制台,但我建议您创建一个新的tsconfig_decl.json文件。 Sadly I didn't find a way to just create the declarations, therefore you need to clean out the dist folder afterward. 遗憾的是,我没有找到创建声明的方法,因此您需要在之后清除dist文件夹。

Example tsconfig_decl.json 示例tsconfig_decl.json

The important properties are declaration , declarationDir and I guess outDir to know which folder to delete. 重要的属性是declarationdeclarationDir ,我猜outDir知道要删除哪个文件夹。

{
  "compilerOptions": {
    "baseUrl": "",
    "declaration": true,
    "declarationDir": "../node_modules/@types/myproject",
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "lib": ["es6", "dom"],
    "mapRoot": "./",
    "module": "es6",
    "moduleResolution": "node",
    "outDir": "../dist/dec-del",
    "sourceMap": true,
    "target": "es5",

    "typeRoots": [
      "../node_modules/@types"
    ]
  }
}

Generate declarations 生成声明

tsc -p "src/tsconfig_decl.json"

Provided the folder structures/barrels are correct, you should be able to use 如果文件夹结构/桶是正确的,您应该可以使用

import { AuthService, UserService } from 'myproject/services';

--------------- Old Answer --------------- ---------------旧答案---------------

If you have this structure 如果你有这个结构

src/app/services SRC /应用/服务
src/app/components SRC /应用/组件
src/app/models SRC /应用/型号
src/app/pipes SRC /应用程序/管

you could create index.ts files (barrels) inside these folders that export all available services/components/... . 你可以在这些文件夹中创建index.ts文件(桶),导出所有可用的服务/组件/ .... Then you can access them using app/services . 然后,您可以使用app/services访问它们。 It's not entirely what you want but you could rename the app folder to get your project name in there or I guess changing the build process may help with that. 这不完全是你想要的,但你可以重命名app文件夹以获取你的项目名称,或者我想改变构建过程可能会有所帮助。

src/app/services/index.ts SRC /应用程序/服务/ index.ts

export * from './auth.service';
export * from './user.service';
...

Using the services 使用服务

import { AuthService, UserService } from 'app/services';
... 

If you have a deeper structure you need to create barrels up the chain or use the relative path on the top level to get the path you want. 如果你有一个更深的结构,你需要在链上创建桶或使用顶层的相对路径来获得你想要的路径。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM