angular2-template-loader产生错误的输出,为什么?

时间:2016-08-24 16:32:53

标签: angular webpack

请观察以下TypeScript文件:

import { Component } from "@angular/core";

@Component({
    selector: 'app-root',
    templateUrl: './app/app.component.html'
})
export class AppComponent {
}

在使用angular2-template-loader之前它工作正常。当我尝试使用后者并运行webpack时,它会失败并显示以下消息:

    polyfills.js     283 kB       1  [emitted]  polyfills
       vendor.js    3.32 MB       2  [emitted]  vendor
     main.js.map    17.2 kB       0  [emitted]  main
polyfills.js.map     353 kB       1  [emitted]  polyfills
   vendor.js.map    3.94 MB       2  [emitted]  vendor
      index.html  607 bytes          [emitted]
    + 912 hidden modules

ERROR in ./src/client/app/app.component.ts
Module not found: Error: Cannot resolve 'file' or 'directory' ./app/app.component.html in C:\Users\markk\IdeaProjects\QuestionarySample2\src\client\app
 @ ./src/client/app/app.component.ts 18:22-57

...
Child html-webpack-plugin for "index.html":
        + 1 hidden modules

C:\Users\markk\IdeaProjects\QuestionarySample2>

(对于其他组件有更多错误,我用省略号替换它们)

加载程序将上述源转换为:

import { Component } from "@angular/core";

@Component({
    selector: 'app-root',
    template: require('./app/app.component.html')
})
export class AppComponent {
}

现在它失败了。

据我了解,原因是 require 在当前目录下工作,而 templateUrl 相对于root。所以,' ./ app / app.component.html'相对于根而言是正确的,但相对于当前位置时是错误的。

值得注意的是,我不在源代码中的任何地方使用 require ,只使用ES6 import 语句,该语句也与当前位置相关。只有Angular2 templateUrl styleUrls 相对于根。

无论如何,我一定是做错了,因为似乎没有人有我的问题。但是我做错了什么?

文件名为 src / client / app / app.component.ts 。源代码目录结构是:

C:.
│   .gitignore
│   karma.conf.js
│   package.json
│   tsconfig.json
│   tslint.json
│   typings.json
│   webpack.config.js
│           
├───config
│       karma-test-shim.js
│       karma.conf.js
│       webpack.common.js
│       webpack.dev.js
│       webpack.prod.js
│       webpack.scratch.js
│       webpack.test.js
│       
└───src
    ├───client
    │   │   global.css
    │   │   index.html
    │   │   main.ts
    │   │   polyfills.ts
    │   │   tsconfig.json
    │   │   vendor.ts
    │   │   
    │   └───app
    │       │   app.component.html
    │       │   app.component.ts
    │       │   app.module.ts
    │       │   app.routing.ts
    │       │   settings.component.ts
    │       │   signout.component.ts
    │       │   
    │       ├───assets
    │       │       ...
    │       │       
    │       ├───questionnaire
    │       │       ...
    │       │       
    │       └───shared
    │               ...
    │               
    └───server
            api.ts
            main.ts
            tsconfig.json         

webpack配置为:

webpack.config.js

module.exports = require('./config/webpack.dev.js'); 

./配置/ webpack.dev.js

var webpackMerge = require('webpack-merge');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var commonConfig = require('./webpack.common.js');
const path = require('path');

module.exports = webpackMerge(commonConfig, {
    // devtool: 'cheap-module-eval-source-map',
    devtool: 'source-map',

    output: {
        publicPath: `http://localhost:${commonConfig.port}/`,
        filename: '[name].js',
        sourceMapFilename: '[name].js.map',
        chunkFilename: '[id].chunk.js'
    },

    plugins: [
        new ExtractTextPlugin('[name].css')
    ],

    devServer: {
        inline: true,
        hot: true,
        progress: true,
        port: commonConfig.port,
        proxy: {
            '/api*': {
                target: `http://localhost:${commonConfig.port - 1}`
            }
        },
        historyApiFallback: true,
        watchOptions: {
            aggregateTimeout: 300,
            poll: 1000
        }
    }
});

./配置/ webpack.common.js

var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
const path = require('path');

module.exports = {
    port: process.env.PORT || 3000,

    entry: {
        polyfills: './src/client/polyfills',
        vendor: './src/client/vendor',
        main: './src/client/main'
    },

    output: {
        path: path.join(__dirname, '../dist/client'),
    },

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

    module: {
        loaders: [
            {
                test: /\.ts$/,
                loaders: ['ts', 'angular2-template-loader']
            },
            {
                test: /\.html$/,
                // loader: 'html'
                loader: 'raw'
            },
            {
                test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/,
                loader: 'file?name=assets/[name].[hash].[ext]'
            },
            // {
            //     test: /\.css$/,
            //     exclude: path.join(__dirname, '../src/client/app'),
            //     loader: ExtractTextPlugin.extract('style', 'css?sourceMap')
            // },
            {
                test: /\.css$/,
                // exclude: path.join(__dirname, '../src/client/app'),
                loader: 'raw'
            }
        ]
    },

    plugins: [
        new webpack.optimize.CommonsChunkPlugin({
            name: ['main', 'vendor', 'polyfills']
        }),

        new HtmlWebpackPlugin({
            template: 'src/client/index.html'
        })
    ]
};

我已经开了一个问题,但我认为这只是我误解的问题 - https://github.com/TheLarkInn/angular2-template-loader/issues/20

编辑1

伙计们,在建议改变之前

templateUrl: './app/app.component.html'

templateUrl: './app.component.html'

请阅读Angular2文档。特别是https://angular.io/docs/ts/latest/guide/architecture.html并查找文本 app / hero-list.component.ts(元数据)。它只出现一次: enter image description here

请注意文件 app / hero-list.component.ts 引用模板 app / hero-list.component.html 。引用是相对于 root ,而不是当前位置。

另外,我已经提到代码在没有加载器和' ./ app / app.component.html'的情况下工作正常。路径。

可能是一个Angular2 RCs的重大变化,我不知道。但这是目前的状况。

1 个答案:

答案 0 :(得分:1)

它与angular2-template-loader无关,当webpack无法找到您需要的文件时,错误来自webpack

angular2-template-loader是什么?

angular2-template-loader在Angular 2 Component元数据中搜索templateUrl和styleUrls声明,并用相应的require语句替换路径。

生成的require语句将由给定的.html和.js文件加载器处理。

如果您转到构建文件并搜索AppComponent,您会发现angular2-template-loader已将templateUrl: "path"转换为 templateUrl: require("path")

@Component({
    selector: 'app-root',
    templateUrl: './app/app.component.html'
})

应该是

@Component({
    moduleId: module.id, //not for webpack
    selector: 'app-root',
    templateUrl: './app.component.html'
})
  

在@Component装饰器中设置moduleId:module.id是这里的关键。如果您没有,那么Angular 2将在根级别查找您的文件。

     

Webpack开发人员可以替代moduleId。   他们可以在运行时加载模板和样式,方法是在模板的开头添加./和引用* component-relative URLS的styles / styleUrls属性。

Question on Stackoverflow

Angular Docs

─app
    │   app.component.html--->same folder
    │   app.component.ts---->same folder
    │   app.module.ts
    │   app.routing.ts
    │   settings.component.ts
    │   signout.component.ts

当您要求templateUrl: './app/app.component.html'查找当前目录中不存在的app文件夹时,您会收到错误。