有没有一种方法可以在不发布到 NPM 的情况下将模板组件集成到本地框架中?

Is there a way to integrate stencil components into frameworks locally without publishing to NPM?

我目前正在测试 stencil js。现在我想编写模板组件并将它们包含在 VUE/React 项目中。 stencil 的官方网站已经展示了如何将它们集成到一个框架中(https://stenciljs.com/docs/overview)。但是他们假设你自己的模板组件库已经发布到 npm。

有没有办法在不先发布的情况下将模板组件本地集成到框架中进行测试?

是的,您可以使用 npm-link

cd my-component-lib
npm link

cd ../my-app
npm link my-component-lib # or whatever you have named the project in package.json

如果您对此有任何问题(例如路径无法正确解析),您也可以尝试打包您的包并安装打包版本,使用 npm-pack:

cd my-component-lib
npm pack

cd ../my-app
npm install ../my-component-lib/my-component-lib-1.0.0.tgz

链接更可取,因为对组件库的更改会立即反映出来(在重建后),而打包时,您必须在每次更改库后重新打包并重新安装它。

您可以使用 TypeScript's path mapping feature.

而不是发布或打包您的包

这允许您像处理已发布的包一样编写导入语句,但在幕后,TypeScript 将导入映射到它们给定的源代码位置。

这是一个 tsconfig.json 的示例,其中路径映射已添加到编译器选项中:

{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "ui-components": ["libs/ui-components"],
      "ui-components/loader": ["libs/ui-components/dist/loader/index.cjs.js"],
      "ui-components-react": ["generated/ui-components-react/src/components.ts"]
    },
    ...

如你所见,它有 3 个映射:核心 Stencil 组件的路径 ui-components,生成的 React 组件的路径,暴露为 ui-components-react,以及生成的loader ui-components/loader 提供自定义元素和 React 包装器之间的桥梁。

我为 Stencil Web Components 创建了一个完整的工作示例,其中包含为 React 生成的绑定和包装器,无需发布任何包:Nx Stencil React.

请注意,此答案基于 @stencil/core 1.14.0 或以下。未来的版本可能会采用不同的方法来生成框架集成。

本地集成可以参考www/build文件夹下的esm.js文件,可以在Vue/React项目的head标签中使用

例如,如果您有以下 2 个应用程序

stencil-components - 模板组件

stencil-react - 将使用组件的示例 React 应用程序。

一旦你 运行 stencil-components by npm run start 它将被托管在 3333(默认)。 在 stencil-reactindex.html 的 head of index.html 中包含以下行将集成组件并在更改时实时重新加载。

<script type="module" src="http://localhost:3333/build/stencil-components.esm.js"></script>

我自己在这方面遇到了很多麻烦,因此将专门针对 Vue 3 提供一个答案,因为 Stencil 的 Framework Integrations 指南似乎仅指 Vue 2。

开始项目

模板组件

遵循 Getting Started 指南 运行 npm init stencil。选择 component 选项。

v2.7.0 中有错误,所以我更新到 v2.8.0 npm i @stencil/core@latest --save-exact

使用 npm run build

构建项目

可选

默认情况下,模板项目配置多个构建目标,为了更容易查看正在使用的构建文件,您可以编辑模板配置以仅包含自定义元素包:

\ stencil.config.ts
outputTargets: [
    {
      type: 'dist-custom-elements-bundle',
    },
    {
      type: 'dist',
      esmLoaderPath: '../loader',
    },
  ],

您还需要 'dist' 类型,以便使用您的自定义元素生成 .d.ts 打字文件(不知道为什么)。

Vue 3 应用程序

使用全局安装的 Vue CLI @vue/cli@4.5.13 创建一个新的 Vue 3 默认项目。

在 Vue 3 中使用 Stencil

安装模板组件项目 npm install --save ../<path>/stencil-component 作为你的 vue 应用程序的依赖。

修复 NPM 模块解析

按照 Vue CLI - Troubleshooting 指南,使用行 config.resolve.symlinks(false),

添加一个 vue.config.js 文件到 Vue 3 项目的根目录

跳过组件解析

在同一个文件中我们需要配置Using Custom Elements in View

\ vue.config.js
module.exports = {
    chainWebpack: (config) => {
        config.resolve.symlinks(false),
        config.module
            .rule("vue")
            .use("vue-loader")
            .tap((options) => ({
                ...options,
                compilerOptions: {
                    isCustomElement: (tag) => tag.includes("my-"),
                },
            }));
    },
};

框架集成

现在我们可以声明自定义元素了,但是以 Vue 3 的方式

\ main.js
import { createApp } from 'vue'
import App from './App.vue'

import { defineCustomElements } from "stencil-component";

defineCustomElements();

createApp(App).mount('#app');

您现在可以正常使用自定义组件了。这是我的 App.vue 文件在破解示例起始代码后的样子:

<template>
    <my-component first="Andy" middle="2K" last="11"></my-component>
</template>

<script>
import { MyComponent } from "stencil-component";

export default {
  name: 'App',
  components: {
    MyComponent
  }
}
</script>

错误

没有 ESLint 配置

No ESLint configuration found in /<path>/stencil-component/dist/custom-elements.

通过告诉 webpack 不要解析 vue.config.js

中的符号链接来修复

未捕获类型错误:class 构造函数必须用 'new'

调用

编译成功后浏览器出现此错误

通过告诉 webpack / vue 不要解析你的自定义组件来解决

自定义组件不可见

没有错误,您的组件显示在 DOM 检查器中,但未出现在页面上。

您需要 defineCustomElements()main.js

未找到组件

我在尝试导入和使用我的组件时遇到过此错误的一些变体,但现在无法重现。完成上述所有操作并重新启动开发服务器对我来说效果很好。