将共享节点模块用于通用类 [英] Using a shared node module for common classes

查看:23
本文介绍了将共享节点模块用于通用类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

目标

所以我有一个具有以下结构的项目:

So I am having a project with this structure:

  • ionic-app
  • firebase功能
  • 共享

目标是在 shared 模块中定义通用接口和类.

The goal is to define common interfaces and classes in the shared module.

限制

我不想将代码上传到npm以在本地使用它,也根本不打算上传代码.它应该100%脱机工作.

I don't want to upload my code to npm to use it locally and am not planning on uploading the code at all. It should 100% work offline.

尽管开发过程应脱机工作,但 ionic-app firebase-functions 模块将部署到firebase(托管和功能).因此, shared 模块中的代码应该在那里可用.

While the development process should work offline, the ionic-app and firebase-functions modules are going to be deployed to firebase (hosting & functions). Therefore, the code from the shared module should be available there.

到目前为止我尝试过的事情

  • 我尝试在打字稿中使用项目引用,但是我有还没开始工作
  • 我尝试将其安装为npm模块,就像此示例的第二个答案一样问题
    • 一开始它似乎运行良好,但是在构建过程中,运行 firebase deploy 时出现这样的错误:
    • I have tried using Project References in typescript, but I have not gotten it close to working
    • I tried it with installing it as an npm module like in the second answer of this question
      • It seems to be working fine at first, but during the build, I get an error like this when running firebase deploy:
      Function failed on loading user code. Error message: Code in file lib/index.js can't be loaded.
      Did you list all required modules in the package.json dependencies?
      Detailed stack trace: Error: Cannot find module 'shared'
          at Function.Module._resolveFilename (module.js:548:15)
          at Function.Module._load (module.js:475:25)
          at Module.require (module.js:597:17)
          at require (internal/module.js:11:18)
          at Object.<anonymous> (/srv/lib/index.js:5:18)
      

      问题

      您是否有使用打字稿配置或NPM制作共享模块的解决方案?

      Do you have a solution for making a shared module using either typescripts config, or NPM?

      请不要将此标记为重复→我已经尝试过在StackOverflow上找到的所有解决方案.

      Please do not mark this as a duplicate → I have tried any solution I have found on StackOverflow.

      其他信息

      配置共享:

      // package.json
      {
        "name": "shared",
        "version": "1.0.0",
        "description": "",
        "main": "dist/src/index.js",
        "types": "dist/src/index.d.ts",
        "files": [
          "dist/src/**/*"
        ],
        "scripts": {
          "test": "echo \"Error: no test specified\" && exit 1"
        },
        "author": "",
        "license": "ISC",
        "publishConfig": {
          "access": "private"
        }
      }
      
      // tsconfig.json
      {
        "compilerOptions": {
          "module": "commonjs",
          "rootDir": ".",
          "sourceRoot": "src",
          "outDir": "dist",
          "sourceMap": true,
          "declaration": true,
          "target": "es2017"
        }
      }
      

      配置功能:

      // package.json
      {
        "name": "functions",
        "scripts": {
          "lint": "tslint --project tsconfig.json",
          "build": "tsc",
          "serve": "npm run build && firebase serve --only functions",
          "shell": "npm run build && firebase functions:shell",
          "start": "npm run shell",
          "deploy": "firebase deploy --only functions",
          "logs": "firebase functions:log"
        },
        "engines": {
          "node": "8"
        },
        "main": "lib/index.js",
        "dependencies": {
          "firebase-admin": "^8.0.0",
          "firebase-functions": "^3.1.0",
          "shared": "file:../../shared"
        },
        "devDependencies": {
          "@types/braintree": "^2.20.0",
          "tslint": "^5.12.0",
          "typescript": "^3.2.2"
        },
        "private": true
      }
      
      
      // tsconfig.json
      {
        "compilerOptions": {
          "baseUrl": "./",
          "module": "commonjs",
          "noImplicitReturns": true,
          "noUnusedLocals": false,
          "rootDir": "src",
          "outDir": "lib",
          "sourceMap": true,
          "strict": true,
          "target": "es2017"
        }
      }
      

      当前状态

      我已经向共享模块添加了一个npm脚本,该脚本会将所有文件(没有index.js)复制到其他模块.这有一个问题,我将重复的代码检入到SCM中,并且我需要在每次更改时都运行该命令.而且,IDE只是将其视为不同的文件.

      I have added a npm script to the shared module, which copies all files (without the index.js) to the other modules. This has the problem, that I check in duplicate code into SCM, and that I need to run that command on every change. Also, the IDE just treats it as different files.

      推荐答案

      前言:我不太熟悉Typescript编译的工作方式以及 package.json 的工作方式.应该定义这样的模块.尽管此解决方案有效,但可以认为是解决当前任务的一种不可靠的方法.

      Preface: I'm not too familiar with how Typescript compilation works and how package.json in such a module should be defined. This solution, although it works, could be considered a hacky way of achieving the task at hand.

      假定以下目录结构:

      project/
        ionic-app/
          package.json
        functions/
          src/
            index.ts
          lib/
            index.js
          package.json
        shared/
          src/
            shared.ts
          lib/
            shared.js
          package.json
      

      部署Firebase服务时,您可以将命令附加到预部署和后部署挂钩.这是通过所需服务的属性 predeploy postdeploy firebase.json 中完成的.这些属性包含一系列顺序命令,分别在部署代码之前和之后运行.此外,使用环境变量 RESOURCE_DIR ( ./functions ./ionic-app 的目录路径)调用这些命令.)和 PROJECT_DIR (包含 firebase.json 的目录路径).

      When deploying a Firebase service, you can attach commands to the predeploy and postdeploy hooks. This is done in firebase.json via the properties predeploy and postdeploy on the desired service. These properties contain an array of sequential commands to run before and after deploying your code respectively. Furthermore, these commands are called with the environment variables RESOURCE_DIR (the directory path of ./functions or ./ionic-app, whichever is applicable) and PROJECT_DIR (the directory path containing firebase.json).

      使用 firebase.json 内部的 functions predeploy 数组,我们可以将共享库的代码复制到部署到该文件夹​​的文件夹中.云功能实例.这样,您可以简单地包括共享代码,就好像它是位于子文件夹中的库一样,也可以使用).

      Using the predeploy array for functions inside firebase.json, we can copy the shared library's code into the folder that is deployed to the Cloud Functions instance. By doing this, you can simply include the shared code as if it were a library located in a subfolder or you can map it's name using Typescript's path mapping in tsconfig.json to a named module (so you can use import { hiThere } from 'shared';).

      predeploy 挂钩定义(使用 shx 以实现Windows兼容性):

      The predeploy hook definition (uses global install of shx for Windows compatibility):

      // firebase.json
      {
        "functions": {
          "predeploy": [
            "shx rm -rf \"$RESOURCE_DIR/src/shared\"", // delete existing files
            "shx cp -R \"$PROJECT_DIR/shared/.\" \"$RESOURCE_DIR/src/shared\"", // copy latest version
            "npm --prefix \"$RESOURCE_DIR\" run lint", // lint & compile
            "npm --prefix \"$RESOURCE_DIR\" run build"
          ]
        },
        "hosting": {
          "public": "ionic-app",
          ...
        }
      }
      

      将复制的库的打字稿源链接到功能打字稿编译器配置:

      Linking the copied library's typescript source to the functions typescript compiler config:

      // functions/tsconfig.json
      {
        "compilerOptions": {
          ...,
          "baseUrl": "./src",
          "paths": {
            "shared": ["shared/src"]
          }
        },
        "include": [
          "src"
        ],
        ...
      }
      

      将模块名称"shared"与复制的库的包文件夹相关联.

      Associating the module name, "shared", to the copied library's package folder.

      // functions/package.json
      {
        "name": "functions",
        "scripts": {
          ...
        },
        "engines": {
          "node": "8"
        },
        "main": "lib/index.js",
        "dependencies": {
          "firebase-admin": "^8.6.0",
          "firebase-functions": "^3.3.0",
          "shared": "file:./src/shared",
          ...
        },
        "devDependencies": {
          "tslint": "^5.12.0",
          "typescript": "^3.2.2",
          "firebase-functions-test": "^0.1.6"
        },
        "private": true
      }
      

      相同的方法可以与托管文件夹一起使用.


      希望这能激发对Typescript编译更熟悉的人提出使用这些钩子的更干净的解决方案.

      The same approach can be used with the hosting folder.


      Hopefully this inspires someone who is more familiar with Typescript compilation to come up with a cleaner solution that makes use of these hooks.

      这篇关于将共享节点模块用于通用类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆