Arhn - архитектура программирования

Модули AngularJS + Webpack + импорт ES6 — проблема с внедрением зависимостей и порядком объединения

Краткое описание проблемы

Я переношу старое приложение AngularJS для использования Webpack и разделяю его на три части, которые я хочу представить в виде модулей AngularJS:

  • src-ts-admin
  • src-ts-общий
  • src-ts-магазин

Например, я хотел бы, чтобы «src-ts-admin» использовал службы из «src-ts-common», но, к сожалению, webpack объединяет файлы в неправильном порядке для внедрения зависимостей AngularJS, так что я получаю такие ошибки, как ..

Error: "[$injector:unpr] Unknown provider: filterServiceProvider <- filterService <- initializerService

.. где initializerService — служба из src-ts-admin, а filterService — из src-ts-common. Суть проблемы в том, что

  • module("ADMIN").service("initializerService") выполняется перед
  • модуль ("ОБЩИЙ"). сервис ("filterService")

.. хотя я не могу определить проблему в зависимостях.

Обзор файла

src-ts-admin: app.ts

Это точка входа в веб-пакет, но не такая интересная. Маршрутизация приложения активирует app.initializer.ts.

import angular from 'angular';
import { appModule } from './app.module';

src-ts-admin: app.module.ts

import angular from 'angular';
import commonModuleName from '../src-ts-common/common.module';

var modulezz;
modulezz = [commonModuleName,'ngRoute', 'ui.router', 'ui.multiselect', 'ui.bootstrap', 'ui.bootstrap-slider', 'ui.bootstrap.buttons', 'duScroll',
            'ngMessages', 'colorpicker.module', 'angular-bind-html-compile', 'pascalprecht.translate'];

export var appModule = angular.module("ADMIN", modulezz);
export default appModule.name;

src-ts-admin: app.initializer.ts

import angular from "angular";
import appModuleName from "./app.module";
import { filterService } from "../src-ts-common/service/filter-service-model";

export class InitializerController {
    static $inject = ...etc...
    constructor(...etc...) {

    /* THIS IS KICKED OFF BY AN ANGULAR ROUTE, THIS KICKS OFF THE InitializerController BELOW */

    }
}
angular.module(appModuleName).controller("initializerController", InitializerController);

export class InitializerService {
    static $inject = ["$stateParams", "$window", "$timeout", "filterService", ...etc...];
    constructor(private $stateParams, private $window, private $timeout, private filterService: filterService, ...etc...) {

        /* THIS IS WHERE THE DEPENDENCY INJECTION FAILS */

    }
}
angular.module(appModuleName).service("initializerService", InitializerService);

src-ts-common: common.module.ts

import angular from 'angular';
export default angular.module("COMMON",[]).name;

src-ts-common: filter.service.ts

import angular from "angular";
import commonModuleName from '../common.module';

export class filterService {
    static $inject = [];
    constructor() {
    /* ...simplified... */
    }
}
angular.module(commonModuleName).service("filterService", filterService);

Мои мысли

Ошибка, которую я получаю, это ..

Error: "[$injector:unpr] Unknown provider: filterServiceProvider <- filterService <- initializerService

.. что указывает мне, что app.initializer.ts выполняется перед filter.service.ts, хотя он импортирует этот файл.

Вы видите какие-либо очевидные ошибки, которые я сделал? Есть ли у вас какие-либо рекомендации по структурированию импорта модулей AngularJS + Webpack и вырезанию файлов?

--- Решение (обновить!) ---

Благодаря https://stackoverflow.com/a/59631154/5244937 я смог решить свою проблему. Шаблон, который я должен был использовать, состоял в том, чтобы инициализировать модули angular (например, angular.module(commonModuleName).service("filterService", filterService);) в файлах app.module.ts и common.module.ts, а НЕ вместе с их реализациями класса.

Вот исправленные файлы:

src-ts-admin: app.ts

/* here i am more or less just kicking off the angular application after i import app.module.ts */
import { appModule } from './app.module';

appModule.run(["$rootScope", "$location", ...,
    function ($rootScope, $location, ...) {
  ..
}

appModule.controller('appController', ['$scope', ..,
    function ($scope: any, ...) {
  ..
}

src-ts-admin: app.module.ts

/** here (1) i am initializing all angular controllers, services, factories from the ADMIN package & (2) importing the COMMON module  */

import angular from 'angular';
import ngRoute from 'angular-route';
import uiRouter from 'angular-ui-router';
import 'angular-messages';
import 'angular-translate';
import dptCommonModuleName from '../src-ts-common/common.module';

var modulezz;
modulezz = [dptCommonModuleName, ngRoute, uiRouter, 'ui.multiselect', 'ui.bootstrap', 'ui.bootstrap-slider', 'ui.bootstrap.buttons', 'duScroll',
        'ngMessages', 'colorpicker.module', 'angular-bind-html-compile', 'pascalprecht.translate'];

export var appModule = angular.module("DPT", modulezz);
export var appModuleName = appModule.name;

/**
 * Services
 */
angular.module(appModuleName).service("systemParameterService", systemParameterService);
angular.module(appModuleName).service("statisticsService", statisticsService);
angular.module(appModuleName).service("deletionCheckService", deletionCheckService);
...

src-ts-admin: app.initializer.ts

/** here i have removed (1) the import of angular.module.ts and (2) the initialization of angular controller and service "initializerController" and "initializationService" */

import angular from "angular";
import { filterService } from "../src-ts-common/service/filter-service-model";

export class InitializerController {
    static $inject = ...etc...
    constructor(...etc...) {

    /* THIS IS KICKED OFF BY AN ANGULAR ROUTE, THIS KICKS OFF THE InitializerController BELOW */

    }
}

export class InitializerService {
    static $inject = ["$stateParams", "$window", "$timeout", "filterService", ...etc...];
    constructor(private $stateParams, private $window, private $timeout, private filterService: filterService, ...etc...) {

        /* THIS IS WHERE THE DEPENDENCY INJECTION FAILS */

    }
}

src-ts-common: common.module.ts

/* here i have added the initialization of the angular service filterService and all other services, factories, .. contained in that module */

var moduleName = angular.module("DPT.COMMON",[]).name
export default moduleName;

angular.module(moduleName).factory("filterModel", function () { return filterModel; });
angular.module(moduleName).factory("filterPresetModel", function () {return filterPresetModel;});
angular.module(moduleName).factory("productModel", function () {return productModel;});
angular.module(moduleName).factory("propertyProfileModel", [function () {return propertyProfileModel;}]);
angular.module(moduleName).factory("propertyValueModel",function () {return propertyValueModel;});

src-ts-common: filter.service.ts

/** здесь я (1) удалил импорт common.module и (2) инициализировал angular.module(..).service("filterService", ..) */

import angular from "angular";

export class filterService {
    static $inject = [];
    constructor() {
    /* ...simplified... */
    }
}

Ответы:


1

Ваши зависимости инвертированы, Module должен импортировать свои зависимости (другие модули или фильтры/сервисы/компоненты).

Если вы последуете этому, ваш AppModule будет импортировать свои дочерние модули, которые, в свою очередь, будут импортировать свои сервисы.

Это означает, что ваши службы должны только экспортировать класс. Соответствующий модуль должен импортировать класс обслуживания, зарегистрировать его в модуле и экспортировать имя модуля. Родительский модуль должен импортировать свои дочерние модули.

// serviceX.js

export class serviceX {
  static $inject=[];
  ...
}
// childModule.js

import {serviceX} from './services/serviceX.js';
import {componentY} from './components/componentY.js';
import angular from 'angular';

export default angular.module('childModule', [])
.service('serviceX', serviceX)
.component('componentY', componentY)
// ... rest of the childModule deps
.name;
// appModule.js

import {externalDep} from 'external-dep';
import childModule from './modules/childModule';
import angular from 'angular';

const appModule = anguler.module('appModule', [externalDep, childModule]).name;

angular.bootstrap(document, [appModule]);
07.01.2020
  • Ты прав. Вместе с приведенным ниже туториалом я исправил структуру импорта и файлов. угловые советы .com/blog/2015/06/ Я обновлю свой исходный пост, указав свое текущее состояние. 08.01.2020
  • Новые материалы

    Коллекции публикаций по глубокому обучению
    Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге https://amundtveit.com - эта публикация дает обзор 25..

    Представляем: Pepita
    Фреймворк JavaScript с открытым исходным кодом Я знаю, что недостатка в фреймворках JavaScript нет. Но я просто не мог остановиться. Я хотел написать что-то сам, со своими собственными..

    Советы по коду Laravel #2
    1-) Найти // You can specify the columns you need // in when you use the find method on a model User::find(‘id’, [‘email’,’name’]); // You can increment or decrement // a field in..

    Работа с временными рядами спутниковых изображений, часть 3 (аналитика данных)
    Анализ временных рядов спутниковых изображений для данных наблюдений за большой Землей (arXiv) Автор: Рольф Симоэс , Жильберто Камара , Жильберто Кейрос , Фелипе Соуза , Педро Р. Андраде ,..

    3 способа решить квадратное уравнение (3-й мой любимый) -
    1. Методом факторизации — 2. Используя квадратичную формулу — 3. Заполнив квадрат — Давайте поймем это, решив это простое уравнение: Мы пытаемся сделать LHS,..

    Создание VR-миров с A-Frame
    Виртуальная реальность (и дополненная реальность) стали главными модными терминами в образовательных технологиях. С недорогими VR-гарнитурами, такими как Google Cardboard , и использованием..

    Демистификация рекурсии
    КОДЕКС Демистификация рекурсии Упрощенная концепция ошеломляющей О чем весь этот шум? Рекурсия, кажется, единственная тема, от которой у каждого начинающего студента-информатика..