Angular html 在组件库中找不到文件

Angular html file not found in component library

我正在为 angular 构建一个组件库,我们将在项目之间共享它。但是当我构建包时,html 文件不会被复制到 dist 文件夹中。我收到错误 angular Failed to load text-input.component.html

这是我的 tsconfig.json:

{
  "compileOnSave": false,
  "compilerOptions": {
    "outDir": "./dist",
    "baseUrl": "src",
    "sourceMap": true,
    "declaration": false,
    "moduleResolution": "node",
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "target": "es5",
    "typeRoots": [
      "node_modules/@types"
    ],
    "lib": [
      "es2016",
      "dom"
    ]
  },
  "exclude": [
    "node_modules",
    "dist",
    "**/*.spec.ts"
  ]
}

这是编译后的组件:

"use strict";
var __extends = (this && this.__extends) || (function () {
    var extendStatics = Object.setPrototypeOf ||
        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
Object.defineProperty(exports, "__esModule", { value: true });
var core_1 = require("@angular/core");
var abstract_input_component_1 = require("./../abstract-input/abstract-input.component");
var TextInputComponent = /** @class */ (function (_super) {
    __extends(TextInputComponent, _super);
    function TextInputComponent() {
        var _this = _super.call(this) || this;
        _this.type = 'text';
        return _this;
    }
    TextInputComponent.prototype.ngOnInit = function () {
        //
    };
    __decorate([
        core_1.Input(),
        __metadata("design:type", Object)
    ], TextInputComponent.prototype, "type", void 0);
    TextInputComponent = __decorate([
        core_1.Component({
            moduleId: module.id,
            selector: 'hp-text-input',
            templateUrl: './text-input.component.html',
            styleUrls: ['./text-input.component.scss']
        }),
        __metadata("design:paramtypes", [])
    ], TextInputComponent);
    return TextInputComponent;
}(abstract_input_component_1.AbstractInputComponent));
exports.TextInputComponent = TextInputComponent;
//# sourceMappingURL=text-input.component.js.map

这是带有模板 url 的未编译组件:

import { Component, OnInit, Input } from '@angular/core';
import { AbstractInputComponent } from './../abstract-input/abstract-input.component';

@Component({
  moduleId: module.id,
  selector: 'hp-text-input',
  templateUrl: './text-input.component.html',
  styleUrls: ['./text-input.component.scss']
})
export class TextInputComponent extends AbstractInputComponent implements OnInit {
  @Input() type = 'text';

  constructor() {
    super();
  }

  ngOnInit() {
    //
  }
}

这是编译好的目录:

这是未编译的目录:

这些是我在 package.json 中的构建脚本:

  "scripts": {
    "clean": "rm -rf dist/",
    "build": "npm run clean && tsc",
    "install": "npm run build"
  },

我尝试过搜索,但大多数结果都已过时或严重依赖更多依赖项。我缺少一些配置吗?

您在这里使用的是moduleId: module.id,所以不需要使用相对路径,

只需从 templateUrlstyleUrls 中删除 ./

@Component({
  moduleId: module.id,
  selector: 'hp-text-input',
  templateUrl: 'text-input.component.html',
  styleUrls: ['text-input.component.scss']
})

我最终使用 gulp 来完成这项任务,因为 angular CLI 尚无法实现。我使用了这个教程:How to set up an angular 2 component library

我必须注意,这可能还不兼容 AOT。但该项目尚未进入那个阶段,因此当我们需要做好生产准备时就会到来。到时候我会更新答案。

=======

更新

我最终使用了 ng-packagr,因为 angular 也采用了它。尽管您需要注意使用与 angular 版本

相对应的版本,但效果很好

我有一个与您的问题直接相关的问题:. Then here I found a meaningful thread on this topic, and moving from link to link I saw the official document Angular Package Format (APF) v5.0,包含以下内容:

Inlining of templates and stylesheets
Component libraries are typically implemented using stylesheets and html templates stored in separate files. While it's not required, we suggest that component authors inline the templates and stylesheets into their FESM files as well as *.metadata.json files by replacing the stylesheetUrls and templateUrl with stylesheets and template metadata properties respectively. This simplifies consumption of the components by application developers.

允许您使用外部 templates/styles 的方式是基于构建过程的深度定制,它应该在编译之前提供对外部 temlates/styles 的人为内联。这些示例可以在那个 GitHub 线程上找到(一个人甚至在 npm with 1k downloads per month). A useful approach is in my ...

上发布了他的解决方案

但我决定走中间路线:

my.component.ts

import template from './my.component.temlate.html'
import style from './my.component.temlate.css'

@Component({
  selector: 'app-my-component',
  template: template + '',
  styles: [style + '']
})

my.component.temlate.html.ts

export default `
<div data-padding-top></div>
...
`

my.component.temlate.css.ts

export default `
:host {
  overflow-anchor: none;
  overflow-y: auto;
}
`

从 angular 6 开始,您可以告诉 angular 编译器在构建期间将您的模板 html 文件转换为内联模板。

angularCompilerOptions 下的 "enableResourceInlining": true 添加到库文件夹中的 tsconfig.lib.json 文件,以将 html 文件转换为 angular 组件的内联模板。

  "angularCompilerOptions": {
    "enableResourceInlining": true
  },