一些背景资料:
我正在尝试将我的角度应用程序合并到这个“metaframework”中,single-spa
我已完成ng eject
并使用webpack以'amd'格式输出包。然后我使用SystemJS导入包。
我认为此设置可能是我收到此错误的原因,因为我在正常运行应用时没有出现此错误。
当我在构造函数中使用forwardRef时,我没有收到此错误。我认为这是因为在调用组件时没有定义服务,这让我觉得导入/提供者的某些东西不起作用。
@Inject(forwardRef(() => TestService)) private testService: TestService
这是得到错误的组件:
import { Component, OnInit, Inject, forwardRef } from '@angular/core';
import { TestService } from '../test.service';
@Component({
selector: 'app-test',
templateUrl: './test.component.html',
styleUrls: ['./test.component.css']
})
export class TestComponent implements OnInit {
constructor(
private testService: TestService
) { }
ngOnInit() {
}
}
这是服务:
import { Injectable } from '@angular/core';
@Injectable()
export class TestService {
constructor() { }
}
app.module.ts:
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { TestComponent } from './test/test.component';
import { TestService } from './test.service';
@NgModule({
declarations: [
AppComponent,
TestComponent
],
imports: [
BrowserModule
],
providers: [ TestService ],
bootstrap: [ AppComponent ]
})
export class AppModule { }
main.ts:
import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
import { environment } from './environments/environment';
// ADD THE FOLLOWING -----------------------------------------
import singleSpaAngular2 from 'single-spa-angular2';
import './polyfills';
// import './styles';
const ngLifecycles = singleSpaAngular2({
// A function that takes in no arguments and returns a DOMElement.
// This dom element is where the angular application will be bootstrapped, mounted, and unmounted.
domElementGetter: domElementGetter,
// An Angular 2 module class. If you're using Typescript or ES6 decorators, this is a class with the @NgModule decorator on it.
mainModule: AppModule,
// The platform with which to bootstrap your module. The "Angular platform"
// refers to whether the code is running on the browser, mobile, server, etc.
// In the case of a single-spa application, you should use the platformBrowserDynamic platform.
angularPlatform: platformBrowserDynamic(),
// An html string that will be put into the DOM Element returned by domElementGetter.
// This template can be anything, but it is recommended that you keeping it simple by making it only one Angular component.
// For example, <my-component /> is recommended, but <div><my-component /><span>Hello</span><another-component /></div> is allowed.
// Generally the root angular component (selector in app.component.ts and index.html)
template: `<example-app />`,
// Router: (optional) The angular router class. If not provided, single-spa-angular2 will assume you are not using @angular/router.
// Router
});
export function bootstrap() {
return ngLifecycles.bootstrap();
}
export function mount() {
return ngLifecycles.mount();
}
export function unmount() {
return ngLifecycles.unmount();
}
function domElementGetter() {
// Make sure there is a div for us to render into
let el = document.getElementById( 'example-child-app' );
if (!el) {
el = document.createElement( 'div' );
el.id = 'example-child-app';
document.body.appendChild( el );
}
return el;
}
// -----------------------------------------------------------
if (environment.production) {
enableProdMode();
}
// platformBrowserDynamic().bootstrapModule(AppModule) // REMOVE THIS
这是我的webpack配置:
const fs = require('fs');
const path = require('path');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const ProgressPlugin = require('webpack/lib/ProgressPlugin');
const CircularDependencyPlugin = require('circular-dependency-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const rxPaths = require('rxjs/_esm5/path-mapping');
const autoprefixer = require('autoprefixer');
const postcssUrl = require('postcss-url');
const cssnano = require('cssnano');
const customProperties = require('postcss-custom-properties');
const { NoEmitOnErrorsPlugin, SourceMapDevToolPlugin, NamedModulesPlugin } = require('webpack');
const { NamedLazyChunksWebpackPlugin, BaseHrefWebpackPlugin } = require('@angular/cli/plugins/webpack');
const { CommonsChunkPlugin } = require('webpack').optimize;
const { AngularCompilerPlugin } = require('@ngtools/webpack');
// const nodeModules = path.join(process.cwd(), 'node_modules'); // REMOVE THIS
// const realNodeModules = fs.realpathSync(nodeModules); // REMOVE THIS
// const genDirNodeModules = path.join(process.cwd(), 'src', '$$_gendir', 'node_modules'); // REMOVE THIS
// const entryPoints = ["inline","polyfills","sw-register","styles","vendor","main"]; // REMOVE THIS
const minimizeCss = false;
const baseHref = "";
const deployUrl = "";
const postcssPlugins = function () {
// safe settings based on: https://github.com/ben-eb/cssnano/issues/358#issuecomment-283696193
const importantCommentRe = /@preserve|@licen[cs]e|[@#]\s*source(?:Mapping)?URL|^!/i;
const minimizeOptions = {
autoprefixer: false,
safe: true,
mergeLonghand: false,
discardComments: { remove: (comment) => !importantCommentRe.test(comment) }
};
return [
postcssUrl([
{
// Only convert root relative URLs, which CSS-Loader won't process into require().
filter: ({ url }) => url.startsWith('/') && !url.startsWith('//'),
url: ({ url }) => {
if (deployUrl.match(/:\/\//) || deployUrl.startsWith('/')) {
// If deployUrl is absolute or root relative, ignore baseHref & use deployUrl as is.
return `${deployUrl.replace(/\/$/, '')}${url}`;
}
else if (baseHref.match(/:\/\//)) {
// If baseHref contains a scheme, include it as is.
return baseHref.replace(/\/$/, '') +
`/${deployUrl}/${url}`.replace(/\/\/+/g, '/');
}
else {
// Join together base-href, deploy-url and the original URL.
// Also dedupe multiple slashes into single ones.
return `/${baseHref}/${deployUrl}/${url}`.replace(/\/\/+/g, '/');
}
}
},
{
// TODO: inline .cur if not supporting IE (use browserslist to check)
filter: (asset) => !asset.hash && !asset.absolutePath.endsWith('.cur'),
url: 'inline',
// NOTE: maxSize is in KB
maxSize: 10
}
]),
autoprefixer(),
customProperties({ preserve: true })
].concat(minimizeCss ? [cssnano(minimizeOptions)] : []);
};
module.exports = {
"resolve": {
"extensions": [
".ts",
".js"
],
"modules": [
"./node_modules",
// "./node_modules" // REMOVE THIS
],
"symlinks": true,
"alias": rxPaths(),
"mainFields": [
"browser",
"module",
"main"
]
},
"resolveLoader": {
"modules": [
"./node_modules",
// "./node_modules" // REMOVE THIS
],
"alias": rxPaths()
},
"entry": {
"main": [
"./src/main.ts"
],
// "polyfills": [ // REMOVE THIS
// "./src/polyfills.ts"
// ],
// "styles": [ // REMOVE THIS
// "./src/styles.css"
// ]
},
"output": {
"path": path.join(process.cwd(), "dist"),
"filename": "[name].bundle.js",
"chunkFilename": "[id].chunk.js",
"crossOriginLoading": false,
"libraryTarget": "amd" // ADD THIS
},
"module": {
"rules": [
{
"test": /\.html$/,
"loader": "raw-loader"
},
{
"test": /\.(eot|svg|cur)$/,
"loader": "file-loader",
"options": {
"name": "[name].[hash:20].[ext]",
"limit": 10000
}
},
{
"test": /\.(jpg|png|webp|gif|otf|ttf|woff|woff2|ani)$/,
"loader": "url-loader",
"options": {
"name": "[name].[hash:20].[ext]",
"limit": 10000
}
},
{
"exclude": [
path.join(process.cwd(), "src/styles.css")
],
"test": /\.css$/,
"use": [
"exports-loader?module.exports.toString()",
{
"loader": "css-loader",
"options": {
"sourceMap": false,
"importLoaders": 1
}
},
{
"loader": "postcss-loader",
"options": {
"ident": "postcss",
"plugins": postcssPlugins,
"sourceMap": false
}
}
]
},
{
"exclude": [
path.join(process.cwd(), "src/styles.css")
],
"test": /\.scss$|\.sass$/,
"use": [
"exports-loader?module.exports.toString()",
{
"loader": "css-loader",
"options": {
"sourceMap": false,
"importLoaders": 1
}
},
{
"loader": "postcss-loader",
"options": {
"ident": "postcss",
"plugins": postcssPlugins,
"sourceMap": false
}
},
{
"loader": "sass-loader",
"options": {
"sourceMap": false,
"precision": 8,
"includePaths": []
}
}
]
},
{
"exclude": [
path.join(process.cwd(), "src/styles.css")
],
"test": /\.less$/,
"use": [
"exports-loader?module.exports.toString()",
{
"loader": "css-loader",
"options": {
"sourceMap": false,
"importLoaders": 1
}
},
{
"loader": "postcss-loader",
"options": {
"ident": "postcss",
"plugins": postcssPlugins,
"sourceMap": false
}
},
{
"loader": "less-loader",
"options": {
"sourceMap": false
}
}
]
},
{
"exclude": [
path.join(process.cwd(), "src/styles.css")
],
"test": /\.styl$/,
"use": [
"exports-loader?module.exports.toString()",
{
"loader": "css-loader",
"options": {
"sourceMap": false,
"importLoaders": 1
}
},
{
"loader": "postcss-loader",
"options": {
"ident": "postcss",
"plugins": postcssPlugins,
"sourceMap": false
}
},
{
"loader": "stylus-loader",
"options": {
"sourceMap": false,
"paths": []
}
}
]
},
{
"include": [
path.join(process.cwd(), "src/styles.css")
],
"test": /\.css$/,
"use": [
"style-loader",
{
"loader": "css-loader",
"options": {
"sourceMap": false,
"importLoaders": 1
}
},
{
"loader": "postcss-loader",
"options": {
"ident": "postcss",
"plugins": postcssPlugins,
"sourceMap": false
}
}
]
},
{
"include": [
path.join(process.cwd(), "src/styles.css")
],
"test": /\.scss$|\.sass$/,
"use": [
"style-loader",
{
"loader": "css-loader",
"options": {
"sourceMap": false,
"importLoaders": 1
}
},
{
"loader": "postcss-loader",
"options": {
"ident": "postcss",
"plugins": postcssPlugins,
"sourceMap": false
}
},
{
"loader": "sass-loader",
"options": {
"sourceMap": false,
"precision": 8,
"includePaths": []
}
}
]
},
{
"include": [
path.join(process.cwd(), "src/styles.css")
],
"test": /\.less$/,
"use": [
"style-loader",
{
"loader": "css-loader",
"options": {
"sourceMap": false,
"importLoaders": 1
}
},
{
"loader": "postcss-loader",
"options": {
"ident": "postcss",
"plugins": postcssPlugins,
"sourceMap": false
}
},
{
"loader": "less-loader",
"options": {
"sourceMap": false
}
}
]
},
{
"include": [
path.join(process.cwd(), "src/styles.css")
],
"test": /\.styl$/,
"use": [
"style-loader",
{
"loader": "css-loader",
"options": {
"sourceMap": false,
"importLoaders": 1
}
},
{
"loader": "postcss-loader",
"options": {
"ident": "postcss",
"plugins": postcssPlugins,
"sourceMap": false
}
},
{
"loader": "stylus-loader",
"options": {
"sourceMap": false,
"paths": []
}
}
]
},
{
"test": /\.ts$/,
"loader": "@ngtools/webpack"
}
]
},
"plugins": [
new NoEmitOnErrorsPlugin(),
new CopyWebpackPlugin([
{
"context": "src",
"to": "",
"from": {
"glob": "assets/**/*",
"dot": true
}
},
{
"context": "src",
"to": "",
"from": {
"glob": "favicon.ico",
"dot": true
}
}
], {
"ignore": [
".gitkeep",
"**/.DS_Store",
"**/Thumbs.db"
],
"debug": "warning"
}),
new ProgressPlugin(),
new CircularDependencyPlugin({
"exclude": /(\\|\/)node_modules(\\|\/)/,
"failOnError": false,
"onDetected": false,
"cwd": "/Users/rmadan/a1/example-child-app"
}),
new NamedLazyChunksWebpackPlugin(),
// new HtmlWebpackPlugin({ // REMOVE THIS
// "template": "./src/index.html",
// "filename": "./index.html",
// "hash": false,
// "inject": true,
// "compile": true,
// "favicon": false,
// "minify": false,
// "cache": true,
// "showErrors": true,
// "chunks": "all",
// "excludeChunks": [],
// "title": "Webpack App",
// "xhtml": true,
// "chunksSortMode": function sort(left, right) {
// let leftIndex = entryPoints.indexOf(left.names[0]);
// let rightindex = entryPoints.indexOf(right.names[0]);
// if (leftIndex > rightindex) {
// return 1;
// }
// else if (leftIndex < rightindex) {
// return -1;
// }
// else {
// return 0;
// }
// }
// }),
new BaseHrefWebpackPlugin({}),
// new CommonsChunkPlugin({ // REMOVE THIS
// "name": [
// "inline"
// ],
// "minChunks": null
// }),
// new CommonsChunkPlugin({ // REMOVE THIS
// "name": [
// "vendor"
// ],
// "minChunks": (module) => {
// return module.resource
// && (module.resource.startsWith(nodeModules)
// || module.resource.startsWith(genDirNodeModules)
// || module.resource.startsWith(realNodeModules));
// },
// "chunks": [
// "main"
// ]
// }),
new SourceMapDevToolPlugin({
"filename": "[file].map[query]",
"moduleFilenameTemplate": "[resource-path]",
"fallbackModuleFilenameTemplate": "[resource-path]?[hash]",
"sourceRoot": "webpack:///"
}),
new CommonsChunkPlugin({
"name": [
"main"
],
"minChunks": 2,
"async": "common"
}),
new NamedModulesPlugin({}),
new AngularCompilerPlugin({
"entryModule": __dirname + '/src/app/app.module#AppModule', // ADD THIS
"mainPath": "main.ts",
"platform": 0,
"hostReplacementPaths": {
"environments/environment.ts": "environments/environment.ts"
},
"sourceMap": true,
"tsConfigPath": "src/tsconfig.app.json",
"skipCodeGeneration": true,
"compilerOptions": {}
})
],
"node": {
"fs": "empty",
"global": true,
"crypto": "empty",
"tls": "empty",
"net": "empty",
"process": true,
"module": false,
"clearImmediate": false,
"setImmediate": false
},
"devServer": {
"historyApiFallback": true
}
};
如果我想查看任何其他文件,请告诉我。