【问题标题】:Uncaught Error: The template specified for component AppComponent is not a string未捕获的错误:为组件 AppComponent 指定的模板不是字符串
【发布时间】:2018-12-03 19:49:31
【问题描述】:

我正在尝试使用 webpack 4.4 将我的 angular 5、webpack 2.2 项目升级到 angular 7。这是我更新的 package.json:

"dependencies": {
    "@angular/animations": "^7.1.0",
    "@angular/cdk": "^7.1.0",
    "@angular/common": "^7.1.0",
    "@angular/compiler": "^7.1.0",
    "@angular/compiler-cli": "^7.1.0",
    "@angular/core": "^7.1.0",
    "@angular/flex-layout": "7.0.0-beta.19",
    "@angular/forms": "^7.1.0",
    "@angular/http": "^7.1.0",
    "@angular/material": "^7.1.0",
    "@angular/platform-browser": "^7.1.0",
    "@angular/platform-browser-dynamic": "^7.1.0",
    "@angular/platform-server": "^7.1.0",
    "@angular/router": "^7.1.0",
    "@types/chart.js": "^2.7.20",
    "@types/datatables.net": "1.10.13",
    "@types/handsontable": "^0.35.0",
    "@types/jquery": "^3.3.5",
    "@types/node": "^10.12.10",
    "angular2-csv": "^0.2.9",
    "aspnet-prerendering": "^3.0.1",
    "aspnet-webpack": "^3.0.0",
    "bootstrap": "^3.3.7",
    "chart.js": "^2.7.2",
    "core-js": "2.5.7",
    "css": "^2.2.4",
    "d3": "^4.7.3",
    "datatables.net": "^2.1.1",
    "datatables.net-bs": "^2.1.1",
    "datatables.net-select": "^1.2.7",
    "datatables.net-select-bs": "^1.2.7",
    "es6-shim": "^0.35.1",
    "event-source-polyfill": "1.0.4",
    "expose-loader": "^0.7.5",
    "isomorphic-fetch": "^2.2.1",
    "jquery": "3.3.1",
    "json-loader": "^0.5.7",
    "ng2-handsontable": "^2.1.0-rc.3",
    "popper.js": "^1.14.6",
    "preboot": "6.0.0-beta.6",
    "reflect-metadata": "0.1.10",
    "rxjs": "^6.3.3",
    "rxjs-compat": "^6.3.3",
    "shepherd.js": "2.0.0-beta.35",
    "to-string-loader": "^1.1.5",
    "typescript-watcher": "0.0.4",
    "url-loader": "1.1.2",
    "webpack-hot-middleware": "^2.24.3",
    "zone.js": "^0.8.26"
  },
  "devDependencies": {
    "@types/jasmine": "3.3.0",
    "angular2-template-loader": "^0.6.0",
    "awesome-typescript-loader": "^5.2.1",
    "css-loader": "0.28.11",
    "extract-text-webpack-plugin": "^4.0.0-beta.0",
    "file-loader": "^2.0.0",
    "html-loader": "1.0.0-alpha.0",
    "html-webpack-plugin": "^4.0.0-beta.4",
    "jasmine-core": "^3.3.0",
    "karma": "^3.1.1",
    "karma-chrome-launcher": "^2.2.0",
    "karma-jasmine": "^2.0.1",
    "karma-sourcemap-loader": "^0.3.7",
    "karma-webpack": "^4.0.0-rc.4",
    "null-loader": "^0.1.1",
    "raw-loader": "0.5.1",
    "rimraf": "^2.5.2",
    "style-loader": "0.20.3",
    "typescript": "3.1.6",
    "webpack": "4.4.1",
    "webpack-cli": "2.0.12",
    "webpack-dev-server": "^3.1.10",
    "webpack-merge": "^4.1.4"
  }

我已经尝试了各种加载器来加载 HTML(有些仍然包含在 package.json 中)。我使用了 raw-loader 和 to-string-loader 之类的加载器来查看它是否会产生任何影响(它不会)。

这是我的 webpack 通用配置:

var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var helpers = require('./helpers');

module.exports = {
    entry: {
        'polyfills': './ClientApp/polyfills.ts',
        'vendor': './ClientApp/vendor.ts',
        'app': './ClientApp/main.ts'
    },

    resolve: {
        extensions: ['.ts', '.js']
    },

    module: {
        rules: [
            {
                test: /\.ts$/,
                loaders: [
                    {
                        loader: 'awesome-typescript-loader',
                        options: { configFileName: helpers.root('ClientApp', 'tsconfig.json') }
                    } , 'angular2-template-loader'
                ]
            },
            {
                test: /\.html$/,
                use: [{
                    loader: 'html-loader'
                }] //'to-string-loader', 
            },
            {
                test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/,
                loader: 'file-loader?name=assets/[name].[hash].[ext]'
            },
            {
                test: /\.css$/,
                exclude: helpers.root('ClientApp', 'app'),
                loader: ExtractTextPlugin.extract({ fallback: 'style-loader', use: 'css-loader?sourceMap' })
            },
            {
                test: /\.css$/,
                include: helpers.root('ClientApp', 'app'),
                loader: 'css-loader' //['raw-loader', 'to-string-loader']
            }
        ]
    },

    optimization:
    {
        splitChunks: {
            cacheGroups: {
                commons: {
                    test: /[\\/]node_modules[\\/]/,
                    name: "vendors",
                    chunks: "all"
                }
            }
        }
    },

    plugins: [
        new webpack.ContextReplacementPlugin(
            /angular(\\|\/)core(\\|\/)fesm5/,
            helpers.root('ClientApp'), //./
            {}
        ),

        new HtmlWebpackPlugin({
            template: 'Views/Home/Index.cshtml'
        })
    ]
};

这就是我为我的组件包含所有模板的方式:

@Component({
    selector: "app",
    template: require("./app.component.html"),
    styles: ["./app.component.css"]
})

(以前是templateUrl: "./app.component.html",好像没什么区别)

现在我被这个错误困住了:

我希望有人可以帮助我解决这个问题,因为我已经被这个错误困住了一周了。谢谢!

编辑 当我使用“styleUrls”而不是“styles”时,会显示一些类似的错误: Uncaught Error: Expected 'styles' to be an array of strings.

【问题讨论】:

    标签: angular webpack angular7


    【解决方案1】:

    如果有人仍然有这个错误,那么在你的 app.component.ts 中添加这一行

    styleUrls: ['./app.component.css']
    

    如果这会生成“未捕获的错误:预期的 'styles' 是一个字符串数组。”然后添加以下加载器希望它能解决所有问题

    {
        test: /\.html$/,
        use: 'html-loader' //raw-loader
    },
    {
        test: /\.css$/,
    //  include: path.join(__dirname, 'src', 'app'),
        use: [
            'to-string-loader', 'css-loader',
        ],
    }
    

    【讨论】:

      【解决方案2】:
      @Component({
          selector: "app",
          templateUrl: "./app.component.html",
          styleUrls: ["./app.component.css"]
      })
      

      您不需要require() 模板或templateUrl,更具体。只需提供正确的相对路径。另请注意,我使用的是templateUrl,而不是templatestyleUrls 也是如此。

      【讨论】:

      • 您好,感谢您的快速回复!我以前在升级之前使用“templateUrl”,效果很好。由于跟踪和错误调试,我碰巧最终使用了“模板”。但是现在 templateUrl 显示与模板相同的错误。此外,当我使用 styleUrls 时,我得到 "Uncaught Error: Expected 'styles' to be an array of strings." 再次,这曾经在 webpack 2.2 的角度 5 中工作。
      • 实际上,TIL,您的原始语法有效。我认为styles 问题将消失,如果您包含您已注释掉的to-string-loader
      • @JasperWiggerink 解决了您的问题。当我尝试将 angular 5 升级到 angular 7.2 时,我现在遇到了同样的问题。如果你能得到它,请建议我解决方案。
      • @Sando 已经很长时间了,所以我不确定是什么解决了它(应该在某个地方记录它,抱歉)。但是,我现在对 html 使用“raw-loader”,对 css 使用“to-string-loader”和“css-loader”。我还用 ExtractTextPlugin 摆脱了第一个 css 规则。希望这对你有帮助!
      【解决方案3】:

      该错误可能与不兼容的 TypeScript 版本有关。

      首先,您不应该直接升级多个主要版本。从 Angular 5 升级到 7 时,先升级到 Angular 6,然后再升级到 v7(参见 https://angular.io/guide/releases#supported-update-paths)。

      使用 CLI 更新功能也很舒服:https://angular.io/guide/releases#supported-update-paths 它注意安装所有相关的包和依赖项(例如正确的打字稿版本),卸载不再使用的角度包(例如,当它们被合并到其他包中时)并提供有关必须重构或重构某些代码的信息如果可能,自动进行。

      无论如何,遵循 Angular 升级指南是个好主意:https://update.angular.io/ 它还告诉您必须采取哪些步骤以及可能需要手动完成哪些操作才能成功升级 Angular。

      但是关于具体问题: 在问题中描述的情况下,Angular 团队可能改变了 template 的处理方式(即它实际上必须是一个真实的字符串)。 require("./app.component.html") 不是字符串。 所以@Peter Kim 的回答应该已经解决了你的问题。

      在从 Angular 7 升级到 Angular 8 时,我遇到了类似的情况:我们为 templateUrl 使用了正确的字符串和正确的路径,但得到了错误

      错误:为组件 XXX 指定的模板不是字符串

      我不完全确定是 TypeScript 版本还是从 commonjsesnext 以及从 "target": "es5"es2015 的变化(参见 tsconfig.json),但我的猜测是第一个。 当这些与 Angular 编译器使用的版本不匹配时,字符串的解释(或更准确地说是它们的类型)可能会有所不同。因此,尽管路径是正确的字符串,但您可能会收到该错误。

      在我的情况下,这有点“明显”,因为虽然我们使用了templateUrl,但我得到了template 错误,这是编译器首先处理的。

      【讨论】:

        【解决方案4】:

        如果有人偶然发现这一点,您应该使用原生 angular '@ngtools/webpack' 插件作为加载器,而不是 'angular2-template-loader':

        const { AngularWebpackPlugin } = require('@ngtools/webpack');
        ...
        module: {
            rules: [
                {
                    test: /\.tsx?$/,
                    loader: '@ngtools/webpack'
                },
            ...    
            ]
        },
        plugins: [
            new AngularWebpackPlugin({
                jitMode: true, // false=AOT by default
            }),
            ...
        ]
        

        在 JIT 模式下,它的工作方式类似于 angular2-template-loader 并在运行时使用 raw-loader,但 AOT 模式更可取。更多https://www.npmjs.com/package/@ngtools/webpack 问题是在 AOT 模式下,大多数 angular compilerOptions 都不起作用(尤其是 defaultEncapsulation)- Angular 使用默认值(截至 12.0.0-rc.1)

        【讨论】:

          猜你喜欢
          • 2019-09-02
          • 2021-08-07
          • 2017-02-17
          • 2018-05-24
          • 2015-01-01
          • 2019-11-27
          • 1970-01-01
          • 2018-02-09
          相关资源
          最近更新 更多