Webpack 2和角1:导出和导入模块

时间:2022-10-29 19:39:40

Hope to get some clarification on why the following doesn't work as expected, hopefully, it's something easy I may have overlooked. Without Webpack the current implementation works as expected.

希望能澄清一下为什么下面的内容没有达到预期效果,希望这是我容易忽略的。如果没有Webpack,当前的实现将按照预期工作。

Ideally, would like to keep current implementation, I feel registering the component/controller/etc should be done in its own file and just point to the relative module. But if this isn't best practice I'd also like to see another suggestion.

理想情况下,我希望保持当前的实现,我认为注册组件/控制器/等等应该在它自己的文件中完成,并且只指向相关的模块。但如果这不是最佳实践,我也想看看另一个建议。

File root.module is where I define the root module and then in the root.component file I tack on the component to that module.

文件根。module是我定义根模块的地方,然后在root.component文件中,我将组件附加到该模块。

Current implementation that doesn't import the module:

不导入模块的当前实现:

//root.component.js
'use strict';

var root = {
  template: require('./root.html')
};

module.exports = angular
  .module('root')
  .component('root', root);
'use strict';

//root.module.js
module.exports = angular
    .module('root', [
        require('./common').name,
        require('./components').name
    ]);

If I do the following works and loads module as expected:

如果我按照预期做以下工作并加载模块:

//root.component.js
'use strict';

var root = {
  template: require('./root.html')
};
module.exports = root;

//root.module.js
'use strict';

module.exports = angular
  .module('root', [
    require('./common').name,
    require('./components').name
  ])
  .component('root', require('./root.component'));

Current directory tree:

当前目录树:

├── ./src
│   ├── ./src/app
│   │   ├── ./src/app/app.less
│   │   ├── ./src/app/app.spec.js
│   │   ├── ./src/app/common
│   │   │   ├── ./src/app/common/app.component.js
│   │   │   ├── ./src/app/common/app.controller.js
│   │   │   ├── ./src/app/common/app.html
│   │   │   ├── ./src/app/common/footer
│   │   │   │   ├── ./src/app/common/footer/app-footer.component.js
│   │   │   │   ├── ./src/app/common/footer/app-footer.controller.js
│   │   │   │   ├── ./src/app/common/footer/app-footer.html
│   │   │   │   └── ./src/app/common/footer/index.js
│   │   │   ├── ./src/app/common/header
│   │   │   │   ├── ./src/app/common/header/app-nav.component.js
│   │   │   │   ├── ./src/app/common/header/app-nav.controller.js
│   │   │   │   ├── ./src/app/common/header/app-nav.html
│   │   │   │   └── ./src/app/common/header/index.js
│   │   │   ├── ./src/app/common/index.js
│   │   │   └── ./src/app/common/sideBar
│   │   │       ├── ./src/app/common/sideBar/app-sidebar.component.js
│   │   │       ├── ./src/app/common/sideBar/app-sidebar.controller.js
│   │   │       ├── ./src/app/common/sideBar/app-sidebar.html
│   │   │       └── ./src/app/common/sideBar/index.js
│   │   ├── ./src/app/components
│   │   │   ├── ./src/app/components/auth
│   │   │   │   ├── ./src/app/components/auth/auth-form
│   │   │   │   │   ├── ./src/app/components/auth/auth-form/auth-form.component.js
│   │   │   │   │   ├── ./src/app/components/auth/auth-form/auth-form.controller.js
│   │   │   │   │   ├── ./src/app/components/auth/auth-form/auth-form.html
│   │   │   │   │   └── ./src/app/components/auth/auth-form/index.js
│   │   │   │   ├── ./src/app/components/auth/auth.service.js
│   │   │   │   ├── ./src/app/components/auth/auth.user.js
│   │   │   │   ├── ./src/app/components/auth/index.js
│   │   │   │   ├── ./src/app/components/auth/login
│   │   │   │   │   ├── ./src/app/components/auth/login/index.js
│   │   │   │   │   ├── ./src/app/components/auth/login/login.component.js
│   │   │   │   │   ├── ./src/app/components/auth/login/login.controller.js
│   │   │   │   │   └── ./src/app/components/auth/login/login.html
│   │   │   │   └── ./src/app/components/auth/register
│   │   │   │       ├── ./src/app/components/auth/register/index.js
│   │   │   │       ├── ./src/app/components/auth/register/register.component.js
│   │   │   │       ├── ./src/app/components/auth/register/register.controller.js
│   │   │   │       └── ./src/app/components/auth/register/register.html
│   │   │   └── ./src/app/components/index.js
│   │   ├── ./src/app/root.component.js
│   │   ├── ./src/app/root.html
│   │   └── ./src/app/root.module.js
│   └── ./src/index.ejs
└── ./webpack.config.js

2 个解决方案

#1


9  

A file should be imported (or more precisely, required, because the application relies on CommonJS modules) in order for it to be executed.

为了执行文件,应该导入文件(或者更准确地说,是必需的,因为应用程序依赖于CommonJS模块)。

In the first snippet root.module.js doesn't contain require('./root.component'), so root.component.js is never executed.

在第一个代码段root.module中。js不包含require('./root.component'),所以不会执行root.component.js。

It should be

它应该是

//root.module.js
module.exports = anglar
  .module('root', [
    require('./common').name,
    require('./components').name
  ])
  .component('root', require('./root.component'));

require('./root.component');

Notice that root.component.js should be required after root module was defined, doing these in opposite order will result in $injector:modulerr error.

注意,在定义根模块之后,root.component.js应该是必需的,按相反的顺序执行这些操作将导致$injector:modulerr错误。

The proven way to eliminate race conditions and utilize modularity is to have one Angular module per one file. In this case it doesn't matter in which order the files are required. It is conventional to export and import module's name property from files that contain Angular modules:

消除竞争条件和利用模块化的证明方法是每个文件有一个角模块。在这种情况下,文件的顺序并不重要。从包含角模块的文件中导出和导入模块名属性是常规做法:

//root.component.js
module.exports = angular.module('root.rootComponent', [])
  .component('root', {
    template: require('./root.html')
  })
  .name;

//root.module.js
var rootComponentModule = require('./root.component');
var commonModule = require('./common');
var componentsModule = require('./components');

module.exports = angular
    .module('root', [
        rootComponentModule,
        commonModule,
        componentsModule
    ])
    .name;

This recipe allows to maintain well-arranged deep hierarchy of highly modular units. This is beneficial for code reusing and testing.

这个配方允许保持高度模块化单元的层次结构。这有利于代码重用和测试。

#2


3  

just want to share my approach with you. I'm using it for quite some time already and it works perfectly.

我只是想和你分享我的方法。我已经用了很长一段时间了,它运行得很好。

// src/components/foo/foo.component.js

import './foo.scss';

export class FooComponent {
    static NAME    = 'foo';
    static OPTIONS = {
        controller: FooComponent,
        template  : require('./foo.template.html'),
        bindings  : {},
    };

    constructor(FooService) {
        'ngInject';
        this._FooService = FooService;
    }

    $onInit() { /* ... */ }
    $onDestroy() { /* ... */ }
    /* ... */
}

// src/components/foo/foo.service.js

export class FooService {
    /* ... */
}


// src/components/foo/index.js

import { FooComponent } from './foo.component';
import { FooService } from './foo.service';

export const FOO_COMPONENT = angular.module('components.foo', [])
    .service('FooService', FooService)        
    .component(FooComponent.NAME, FooComponent.OPTIONS)
    .name;


// src/components/index.js

export { FOO_COMPONENT } from './foo';
export { BAR_COMPONENT } from './bar';
/* ... */


// src/app/users/index.js
import { CORE } from 'shared/core';

import { 
    FOO_COMPONENT,
    BAR_COMPONENT,
} from 'components';

import { USERS_LIST_COMPONENT } from './users-list';
import { USER_PROFILE_COMPONENT } from './user-profile';

/* ... */

export const USERS_MODULE = angular
    .module('app.users', [
        CORE,
        FOO_COMPONENT,
        BAR_COMPONENT,
        USERS_LIST_COMPONENT,
        USER_PROFILE_COMPONENT,
    ])
    .name


// src/app/index.js
import { USERS_MODULE } from './users';
import { PRODUCTS_MODULE } from './users';

import { AppComponent } from './app.component';

export const APP_MODULE = angular
    .module('app', [
        USERS_MODULE,
        PRODUCTS_MODULE,
    ])
    .component(AppComponent.NAME, AppComponent.OPTIONS)
    .name;

#1


9  

A file should be imported (or more precisely, required, because the application relies on CommonJS modules) in order for it to be executed.

为了执行文件,应该导入文件(或者更准确地说,是必需的,因为应用程序依赖于CommonJS模块)。

In the first snippet root.module.js doesn't contain require('./root.component'), so root.component.js is never executed.

在第一个代码段root.module中。js不包含require('./root.component'),所以不会执行root.component.js。

It should be

它应该是

//root.module.js
module.exports = anglar
  .module('root', [
    require('./common').name,
    require('./components').name
  ])
  .component('root', require('./root.component'));

require('./root.component');

Notice that root.component.js should be required after root module was defined, doing these in opposite order will result in $injector:modulerr error.

注意,在定义根模块之后,root.component.js应该是必需的,按相反的顺序执行这些操作将导致$injector:modulerr错误。

The proven way to eliminate race conditions and utilize modularity is to have one Angular module per one file. In this case it doesn't matter in which order the files are required. It is conventional to export and import module's name property from files that contain Angular modules:

消除竞争条件和利用模块化的证明方法是每个文件有一个角模块。在这种情况下,文件的顺序并不重要。从包含角模块的文件中导出和导入模块名属性是常规做法:

//root.component.js
module.exports = angular.module('root.rootComponent', [])
  .component('root', {
    template: require('./root.html')
  })
  .name;

//root.module.js
var rootComponentModule = require('./root.component');
var commonModule = require('./common');
var componentsModule = require('./components');

module.exports = angular
    .module('root', [
        rootComponentModule,
        commonModule,
        componentsModule
    ])
    .name;

This recipe allows to maintain well-arranged deep hierarchy of highly modular units. This is beneficial for code reusing and testing.

这个配方允许保持高度模块化单元的层次结构。这有利于代码重用和测试。

#2


3  

just want to share my approach with you. I'm using it for quite some time already and it works perfectly.

我只是想和你分享我的方法。我已经用了很长一段时间了,它运行得很好。

// src/components/foo/foo.component.js

import './foo.scss';

export class FooComponent {
    static NAME    = 'foo';
    static OPTIONS = {
        controller: FooComponent,
        template  : require('./foo.template.html'),
        bindings  : {},
    };

    constructor(FooService) {
        'ngInject';
        this._FooService = FooService;
    }

    $onInit() { /* ... */ }
    $onDestroy() { /* ... */ }
    /* ... */
}

// src/components/foo/foo.service.js

export class FooService {
    /* ... */
}


// src/components/foo/index.js

import { FooComponent } from './foo.component';
import { FooService } from './foo.service';

export const FOO_COMPONENT = angular.module('components.foo', [])
    .service('FooService', FooService)        
    .component(FooComponent.NAME, FooComponent.OPTIONS)
    .name;


// src/components/index.js

export { FOO_COMPONENT } from './foo';
export { BAR_COMPONENT } from './bar';
/* ... */


// src/app/users/index.js
import { CORE } from 'shared/core';

import { 
    FOO_COMPONENT,
    BAR_COMPONENT,
} from 'components';

import { USERS_LIST_COMPONENT } from './users-list';
import { USER_PROFILE_COMPONENT } from './user-profile';

/* ... */

export const USERS_MODULE = angular
    .module('app.users', [
        CORE,
        FOO_COMPONENT,
        BAR_COMPONENT,
        USERS_LIST_COMPONENT,
        USER_PROFILE_COMPONENT,
    ])
    .name


// src/app/index.js
import { USERS_MODULE } from './users';
import { PRODUCTS_MODULE } from './users';

import { AppComponent } from './app.component';

export const APP_MODULE = angular
    .module('app', [
        USERS_MODULE,
        PRODUCTS_MODULE,
    ])
    .component(AppComponent.NAME, AppComponent.OPTIONS)
    .name;