在 Angular2+Webpack 中使用 templateUrl 的相对路径

Posted

技术标签:

【中文标题】在 Angular2+Webpack 中使用 templateUrl 的相对路径【英文标题】:Using relative path for templateUrl in Angular2+Webpack 【发布时间】:2016-08-17 06:18:06 【问题描述】:
import Component from 'angular2/core';

@Component(
  selector: 'app',
  styleUrls: ['./app.component.less'],
  templateUrl: './app.component.html'
)
export class AppComponent 
  name:string = 'Demo'

使用 templateUrl 和 styleUrls 的相对路径时,我得到:错误 404,找不到文件:

zone.js: 101 GET http://localhost/app.component.html 404(未找到)

代码:https://github.com/Dreampie/angular2-demo

我觉得这不是很好的设计,因为在不同的情况下可能构建目录不一样,我可以将其更改为相对当前路径吗?

raw-loader 可以解决这个问题,但是html-loader,less-loader 不适用于template,styles,它只适用于string,所以为什么不支持它们呢?

import Component from 'angular2/core';

@Component(
  selector: 'app',
  styles: [require('./app.component.less')],
  template: require('./app.component.html')
)
export class AppComponent 
  name:string = 'Demo'

得到其他错误:

browser_adapter.js:77 EXCEPTION: Error during instantiation of Token Promise<ComponentRef>!.BrowserDomAdapter.logError
browser_adapter.js:77 ORIGINAL EXCEPTION: Expected 'styles' to be an array of strings.

【问题讨论】:

【参考方案1】:

./(单点)表示法仅适用于 ts 路径,不适用于 html 或 css 路径。

这些路径是相对于 index.html 的,所以根据你的文件结构,这应该可以工作

@Component(
  selector: 'app',
  styleUrls: ['app.component.less'],
  templateUrl: 'app.component.html'
)

【讨论】:

不行,还是不能运行,因为文件是从根目录开始读取的 然后把你的index.htmlsrc拉到根目录,把路径改成src/app.component.html,我认为首先应该是这样,你为什么要放@987654326 @ 在某个子目录中? 如果我有其他模块,我想把模板放在自己的模块目录中,所以我必须从root写,谢谢你的帮助,现在我用raw-loader来解决它【参考方案2】:

让我补充一些信息。

为什么 Angular 不能从组件文件的位置计算 HTML 和 CSS URL?

不幸的是,该位置并不容易知道。 Angular 应用程序可以通过多种方式加载:从单个文件、从 SystemJS 包或从 CommonJS 包,等等。由于加载策略的多样性,在运行时很难判断这些文件实际驻留在哪里。

Angular 唯一可以确定的位置是 index.html 主页的 URL。因此,默认情况下,它会解析相对于 index.html 的 URL 的模板和样式路径。这就是为什么我们之前使用 app/ 基本路径前缀编写 CSS 文件 URL。

Official Angular Docu

【讨论】:

我认为从根路径读取不是很好的设计,因为不同情况下可能构建目录不一样,我可以将其更改为相对当前路径吗?【参考方案3】:

你需要尝试

@Component(
  selector: 'app',
  template: require('./app.component.html'),
  styles: [
    require('./app.component.less').toString()
      or
    String(require('./app.component.less'))
      or
    add css-to-string in your webpack conf (test: /\.css$/, loaders: ['css-to-string', 'style', 'css'])
)

【讨论】:

【参考方案4】:

将 moduleId 属性设置为 module.id 以进行相对于模块的加载,以便 url 是相对于组件的。

@Component(
  moduleId: module.id,
  selector: 'app',
  styleUrls: ['app.component.less'],
  templateUrl: 'app.component.html'
)

【讨论】:

【参考方案5】:

例如,如果您使用 SystemJS,请在此处查看我的答案:https://***.com/a/40694657/986160

您可以使用 model.id 并将其从您的构建路径(带有 js 的)转换为带有 ts、css 和 html 的构建路径。这样你就可以在 Angular 2 中为你的模板和样式使用相对路径,没问题

@Component(
   moduleId: module.id.replace("/dist/", "/"),
...
);

【讨论】:

【参考方案6】:

在我的案例中,我注意到了同样的错误。原因

预期的“样式”是一个字符串数组

在我的例子中是 css-loader,它用于加载 CSS 文件并通过管道传输到 angular2-template-loader

我从调试中了解到,css-loader 对 CSS 文件中的更改进行了一些“智能”检测,如果没有任何更改,则 CSS 文件不会被 webpack 模块导出为字符串。

因为它只是 hello word 应用程序,所以我的解决方案非常简单:将 css-loader 替换为 raw-loader。这是我的装载机版本:

loaders: [
    
        include: [srcPath],
        test: /\.js$/,
        loader: 'babel',
        query: 
            presets: ['es2015']
        
    ,
    
        include: [srcPath],
        test: /\.js$/,
        loader: 'angular2-template-loader',
        query: 
            keepUrl: true
        
    ,
    
        include: [srcPath],
        test: /\.(html|css)$/,
        loader: 'raw',
        query: 
            minimize: true
        
    
]

【讨论】:

【参考方案7】:

WebPack2 不再需要这个 moduleId

【讨论】:

以上是关于在 Angular2+Webpack 中使用 templateUrl 的相对路径的主要内容,如果未能解决你的问题,请参考以下文章

Angular2 Webpack 和 Express

如何使用 Chrome 工作区保存使用 Angular2 + webpack 在本地更改的 CSS?

如何使用 webpack 和 angular2 为生产部署代码

将引导程序添加到 angular2-seed 项目的 webpack 包中

带有 Angular2 和 VS 2015 的 Webpack

Angular2 webpack:如何导入引导 css