Objetivo
Então, eu estou tendo um projeto com esta estrutura:
- ionic-app
- firebase-functions
- compartilhado
O objetivo é definir interfaces e classes comuns no shared
módulo.
Restrições
Não quero fazer upload do meu código para o npm para usá-lo localmente e não pretendo fazer o upload do código. Deve 100% funcionar offline.
Enquanto o processo de desenvolvimento deve funcionar offline, os módulos ionic-app
e firebase-functions
serão implantados na firebase (hospedagem e funções). Portanto, o código do shared
módulo deve estar disponível lá.
O que eu tentei até agora
- Eu tentei usar as referências do projeto em texto datilografado, mas não cheguei nem perto de trabalhar
- Eu tentei instalá-lo como um módulo npm, como na segunda resposta desta pergunta
- Parece estar funcionando bem no começo, mas durante a compilação, recebo um erro como este ao executar
firebase deploy
:
- Parece estar funcionando bem no começo, mas durante a compilação, recebo um erro como este ao executar
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)
Questão
Você tem uma solução para criar um módulo compartilhado usando a configuração de scripts de texto ou o NPM?
Por favor, não marque isso como duplicado → Tentei qualquer solução encontrada no StackOverflow.
Informação adicional
Configuração para compartilhada:
// 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"
}
}
Configuração para funções:
// 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"
}
}
Alma atual
Eu adicionei um script npm ao módulo compartilhado, que copia todos os arquivos (sem o index.js) para os outros módulos. Isso tem o problema: eu verifico o código duplicado no SCM e preciso executar esse comando em todas as alterações. Além disso, o IDE apenas o trata como arquivos diferentes.
fonte
Outra solução possível, se você estiver usando o git para gerenciar seu código, está usando
git submodule
. Usandogit submodule
você é possível incluir outro repositório git em seu projeto.Aplicado ao seu caso de uso:
git submodule add <shared-git-repository-link>
dentro dos seus principais projetos para vincular o repositório compartilhado.Aqui está um link para a documentação: https://git-scm.com/docs/git-submodule
fonte
Se entendi seu problema corretamente, a solução é mais complexa do que uma única resposta e depende em parte da sua preferência.
Abordagem 1: cópias locais
Você pode usar o Gulp para automatizar a solução de trabalho que você já descreveu, mas o IMO não é muito fácil de manter e aumenta drasticamente a complexidade se em algum momento outro desenvolvedor entrar.
Abordagem 2: Monorepo
Você pode criar um único repositório que contém todas as três pastas e conectá-las para que elas se comportem como um único projeto. Como já foi respondido acima, você pode usar o Lerna . Isso requer um pouco de configuração, mas, uma vez concluídas, essas pastas se comportarão como um único projeto.
Abordagem 3: Componentes
Trate cada uma dessas pastas como um componente autônomo. Dê uma olhada no Bit . Isso permitirá que você configure as pastas como partes menores de um projeto maior e crie uma conta privada que terá como escopo esses componentes apenas para você. Uma vez configurado inicialmente, ele permitirá que você aplique atualizações nas pastas separadas e a pasta pai que as usa obterá as atualizações automaticamente.
Abordagem 4: Pacotes
Você disse especificamente que não deseja usar o npm, mas quero compartilhá-lo, porque atualmente estou trabalhando com uma configuração conforme descrito abaixo e está fazendo um trabalho perfeito para mim:
npm
ouyarn
para criar um pacote para cada pasta (você pode criar pacotes com escopo definido para ambos, para que o código esteja disponível apenas para você, se essa for sua preocupação).Funciona como um encanto e, quando os pacotes são vinculados ao desenvolvimento local, ele funciona totalmente offline e, na minha experiência - cada pasta é escalável separadamente e muito fácil de manter.
Nota
Os pacotes 'child' já estão pré-compilados no meu caso, pois são muito grandes e eu criei tsconfigs separados para cada pacote, mas o mais bonito é que você pode alterá-lo facilmente. No passado, eu usei texto datilografado no módulo e arquivos compilados, e também arquivos js brutos, então a coisa toda é muito, muito versátil.
Espero que isto ajude
***** ATUALIZAÇÃO **** Para continuar no ponto 4: peço desculpas, meu mal. Talvez eu tenha entendido errado, porque, até onde eu sei, você não pode vincular um módulo se ele não for carregado. No entanto, aqui está:
firebase-functions
para isso. Você o compila ou usa ts brutos, dependendo da sua preferência.firebase-functions
como uma dependência.tsconfig.json
, adicione"paths": {"firebase-functions: ['node_modules/firebase-functions']"}
resolve: {extensions: ['ts', 'js'], alias: 'firebase-functions': }
Dessa forma, você faz referência a todas as suas funções exportadas do
firebase-functions
módulo simplesmente usandoimport { Something } from 'firebase-functions'
. O Webpack e o TypeScript o vincularão à pasta de módulos do nó. Com essa configuração, o projeto pai não se importará se ofirebase-functions
módulo estiver escrito em TypeScript ou javascript vanilla.Uma vez configurado, ele funcionará perfeitamente para a produção. Em seguida, para vincular e trabalhar offline:
firebase-functions
projetar e escrevernpm link
. Ele criará um link simbólico local para sua máquina e mapeará o link com o nome que você definiu em package.json.npm link firebase-functions
, o que criará o link simbólico e mapeie a dependência das funções do firebase para a pasta em que você o criou.fonte
Todos os módulos npm são instalados localmente e sempre funcionam offline, mas se você não deseja publicar seus pacotes publicamente para que as pessoas possam vê-lo, é possível instalar o registro privado do npm.
O ProGet é um servidor de repositório privado NuGet / Npm disponível para janelas que você pode usar em seu ambiente privado de desenvolvimento / produção para hospedar, acessar e publicar seus pacotes privados. Embora seja no Windows, mas tenho certeza que existem várias alternativas disponíveis no Linux.
Aqui está o nosso cenário de construção / implantação.
.npmrc
que contémregistry=https://private-npm-repository
.bundled dependencies
qual contém todos os pacotes internosnode_modules
e o servidor de produção nunca precisa acessar os pacotes NPM ou NPM privados, pois todos os pacotes necessários já estão empacotados.O uso do repositório npm privado tem várias vantagens,
fonte
A ferramenta que você está procurando é
npm link
.npm link
fornece links simbólicos para um pacote npm local. Dessa forma, você pode vincular um pacote e usá-lo em seu projeto principal sem publicá-lo na biblioteca de pacotes npm.Aplicado ao seu caso de uso:
npm link
dentro da suashared
embalagem. Isso definirá o destino do link simbólico para instalações futuras.functions
pacote e usenpm link shared
para vincular o pacote compartilhado e adicioná-lo aonode_modules
diretórioAqui está um link para a documentação: https://docs.npmjs.com/cli/link.html
fonte