これは私のセットアップでは機能しているようです。つまり、 package.json
がapi/
ワークスペースの下にある場合でも、 deploy
はルートnode_modules
からパッケージを取得します( functions/
代わりに別のフォルダ名を使用しました)。 ここで修正が必要なものは他にありますか?
編集:さらに、 package.json
をapi/dist
にコピーして、 deploy
ます。
// firebase.json
...
"functions": {
"source": "api/dist"
},
...
したがって、2レベルのネストでも、ルートnode_modules
正常に解決されます。
@dinvladレポを共有できますか?
@orouzは残念ながらまだですが、今のところクローズドソースです。
誰かがこの問題に取り組むことができましたか? 簡単なサンプルプロジェクトを共有すると非常に便利です。
@audkar現在、私はlerna.js.orgを使用してrun
コマンドを使用して、次のフォルダー構造を持つ各サブフォルダーでnpmスクリプトを実行します。
- service1/
| - .firebaserc
| - firebase.json
- service2/
| - .firebaserc
| - firebase.json
- app1/
| - .firebaserc
| - firebase.json
- app2/
| - .firebaserc
| - firebase.json
- firestore/
| - firestore.rules
| - firestore.indexes.json
- etc...
各サービスのfirebase.json
ファイルが互いに踏みつけないようにすることは、ユーザーに任されています。 機能グループとマルチサイト名ターゲティングを使用するという単純な規則は、これがクラウド機能とホスティングで解決されることを意味します。 Firestore / GCSルールの解決策はまだありませんが、それらを分割することは理想的ではないかもしれません...
以前にここで説明しました-https://github.com/firebase/firebase-tools/issues/1116
@jthegedusお返事ありがとうございます。 でもこのチケットの発行は違うと思います。 糸のワークスペースを使おうとしています。 また、Firebaseツールは関数をアップロードするときにシンボリックリンクの依存関係を取得しないようです
ああ、まあまあ、私はそのウサギの穴を自分で避けました
問題は何か詳しく教えていただけますか? 上記のように、 api
とapp
ワークスペースを含むベアヤーンを使用し、 yarn workspace api build && yarn workspace app build
を使用してビルドします(それぞれに固有のbuild
スクリプトを使用)ワークスペース)。 ビルドスクリプト
1) outDir
を含むTSコードをそれぞれapi/dist
とapp/dist
コンパイルします
2)対応するpackage.json
ファイルをdist
ディレクトリにコピーします
3) yarn.lock
を_root_フォルダーからdist
ディレクトリにコピーします
次に、_root_フォルダーからyarn firebase deploy
を実行すると、問題なくapi/dist
とapp/dist
両方が取得されます。 私のfirebase.json
は次のようになります
"functions": {
"source": "api/dist"
},
"hosting": {
"public": "app/dist",
残念ながら、私はまだ完全なコードを共有することはできませんが、この設定が重要です、afaik。
また、私は間違っているかもしれませんが、 firebase deploy
スクリプトは実際にはnode_modules
ディレクトリを使用していないと思います。 dist
ディレクトリからコードpackage.json
とyarn.lock
を取得し、残りを実行すると思います。
それは本当だ。 firebase.jsonの「functions.ignore」のデフォルト値は
["node_modules"]なので、アップロードされません。 私はあなたがそれを上書きできると信じています
ただし、いくつかのローカルモジュールを出荷したい場合。
月、2019年6月17日には、6:58 PMデニス・ロジノブ[email protected]
書きました:
また、私は間違っているかもしれませんが、firebasedeployスクリプトはそうではないと思います
実際にはnode_modulesディレクトリを使用してください。 私はそれがちょうど拾うと思います
distディレクトリのcod、package.json、yarn.lockは、
残り。—
このスレッドにサブスクライブしているため、これを受け取っています。
このメールに直接返信し、GitHubで表示してください
https://github.com/firebase/firebase-tools/issues/653?email_source=notifications&email_token=ACATB2U73VS2KIILUVRFFB3P3A6NPA5CNFSM4EOR24GKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2
またはスレッドをミュートします
https://github.com/notifications/unsubscribe-auth/ACATB2U3Q2TLVBICRJ3B5OLP3A6NPANCNFSM4EOR24GA
。
@dinvladはい、 package.json
と、展開後にクラウドにdepsをインストールするときに使用するロックファイルが必要です。
他の問題で最初に概説されたシナリオは、ワークスペース内で共有パッケージを使用することと、スコープの巻き上げに関するいくつかの問題であったと思います。 私はこのように毛糸を使用していなかったので、私はそこで読んだものからしか推測することができません。
@samtstern @jthegedusありがとう、知ってよかった!
私たちは皆、さまざまな問題について話しているようです。 yarn workspaces
問題について説明しようと思います。
プロジェクトのレイアウト
- utilities/
| - package.json
- functions/
| - package.json
- package.json
_./package.json_
{
"private": true,
"workspaces": ["functions", "utilities"]
}
_functions / package.json_
{
<...>
"dependencies": {
"utilities": "1.0.0",
<...>
}
}
関数の展開中にエラーが発生しました:
Deployment error.
Build failed: {"error": {"canonicalCode": "INVALID_ARGUMENT", "errorMessage": "`gen_package_lock` had stderr output:\nnpm WARN deprecated [email protected]: use String.prototype.padStart()\nnpm ERR! code E404\nnpm ERR! 404 Not Found: [email protected]\n\nnpm ERR! A complete log of this run can be found in:\nnpm ERR! /builder/home/.npm/_logs/2019-06-18T07_10_42_472Z-debug.log\n\nerror: `gen_package_lock` returned code: 1", "errorType": "InternalError", "errorId": "1971BEF9"}}
関数はエミュレーターでローカルに正常に動作します。
node_modules
アップロードしています(_firebase.json_のfunctions.ignore
を使用)。 結果は同じです。
utilities
が_node-modules_ node_modules/utilities -> ../../utilities
にsyslinkとして作成されているためだと思います
アップロード時にfirebase-toolsにシンボリックリンクされたモジュールのコンテンツが含まれていない可能性がありますか(逆参照なし)?
申し訳ありませんが、 firebase.json
どのフォルダーにあるかを明確にできますか(そしてfunctions
構成セクションを表示できますか)。
_firebase.json_はルートフォルダにありました。 構成は標準でした。 このようなSmth:
"functions": {
"predeploy": [
"yarn --cwd \"$RESOURCE_DIR\" run lint",
"yarn --cwd \"$RESOURCE_DIR\" run build"
],
"source": "functions",
"ignore": []
},
<...>
シンボリックリンクであるnode_modules/utilities
を除いて、すべてが期待どおりにデプロイされました(_node_modules_を含む)。
私は、次のようないくつかのスクリプトを作成することで、この問題を回避することができます。
yarn pack
)。 たとえば、これにより_utilities.tgz_が作成されます。dependencies { "utilities": "1.0.0"
-> dependencies { "utilities": "file:./utilities.tgz"
アップロード前の出力ディレクトリコンテンツ:
- dist
| - lib
| | -index.js
| - utilities.tgz
| - package.json <---------- This is modified to use *.tgz for workspaces
@audkar今日、私はあなたと同じ問題に遭遇しました。
LernaとYarnの両方のワークスペースは初めてです。 私が理解しているように、Lernaを使用することもできます。 それは何らかの形で役立ちますか?
あなたの回避策は私には少し複雑に思えます🤔
また、 `--cwd" $ RESOURCE_DIR "は何のためにあるのでしょうか?
--cwd
は「現在の作業ディレクトリ」を表し、 $RESOURCE_DIR
はソースディレクトリの値(この場合はfunctions
)を保持します。 このフラグを追加すると、 yarn
がルートではなくfunctions
ディレクトリで実行されるようになります
@audkarああなるほど。 したがって、 yarn workspace functions lint
とyarn workspace functions build
でも同じことができます。
@dinvladなぜdistフォルダーをターゲットにして、そこにあるものをコピーしているのかは私にはdist/index.js
を指す場合、同じように機能するはずです。 次に、sourceをapi / distではなくapiに設定する必要があります。
@dinvladコメントからyarn workspace
コマンドを学びましたが、何らかの理由で機能しないようです。 こちらをご覧ください。 何か案が?
ここで少し話題から外れてすみません。 ノイズを最小限に抑えるために、SOでコメントするかもしれません。
@ 0x80 package.json
をapi/dist
にコピーし、 firebase.json
をapi/dist
ポイントするので、「ビルドされた」ファイルのみがクラウド関数内にパッケージ化されます。 firebase.json
をapi
にポイントするとどうなるかわかりません-おそらく、 api/dist
( main
基づく)の中にあるものだけをパッケージ化するのに十分賢いでしょうpackage.json
main
属性)。 しかし、 api/dist
指すだけの方がクリーンだと思いました。
yarn workspace
、私はSOで応答しました;)
@dinvladは、ポイントしたもののルートをバンドルしますが、
@audkarと同様の回避策を使用しました。
{
"functions": {
"source": "packages/cloud-functions",
"predeploy": ["./scripts/pre-deploy-cloud-functions"],
"ignore": [
"src",
"node_modules"
]
}
}
次に、pre-deploy-cloud-functionsスクリプトは次のとおりです。
#!/usr/bin/env bash
set -e
yarn workspace @gemini/common lint
yarn workspace @gemini/common build
cd packages/common
yarn pack --filename gemini-common.tgz
mv gemini-common.tgz ../cloud-functions/
cd -
cp yarn.lock packages/cloud-functions/
yarn workspace @gemini/cloud-functions lint
yarn workspace @gemini/cloud-functions build
また、packages / cloud-functionsには、追加のgitignoreファイルがあります。
yarn.lock
*.tgz
これが私のために働いたものです
- root/
| - .firebaserc
| - firebase.json
- packages/
| - package1/
| - functions/
| - dist/
| - src/
| packages.json
そしてroot/firebase.json
:
`` `
{{
"関数": {
"predeploy": "npm --prefix" $ RESOURCE_DIR "run build"、
"ソース": "パッケージ/関数"
}
}
「」
@kaminskypavelは、packages / package1(または他の兄弟パッケージ)に依存するパッケージ/関数ですか?
@ 0x80ポジティブ。
モノレポについて私が誤解していた根本的なことがあったと思います。 共有パッケージを実際にNPMに公開しなくても、パッケージを共有し、そのパッケージを使用してアプリをデプロイできると想定しました。
FirebaseやNow.shなどのデプロイでは通常コードがアップロードされ、クラウドでインストールとビルドが行われるため、これは不可能なようです。 私は正しいですか?
@kaminskypavel私はあなたのアプローチを試しましたが、それは機能しますが、最初にパッケージをNPMに公開した後でのみです。 私の場合、パッケージはプライベートであるため、最初は「見つかりません」というエラーが発生しました。そのため、ここで説明するように、.npmrcファイルをクラウド関数パッケージのルートに追加する必要もありまし
@audkar共通パッケージをNPMに公開していますか、それとも公開されていない共有コードを使用してデプロイしようとしていますか?
@ 0x80私はこの理解についてあなたと一緒です-FirebaseFunctionのデプロイは、デプロイを高速化するという名目で、package.jsonで指定されたすべてのパッケージがnpmで利用可能になると(誤って)想定していると思います。
ヤーンワークスペースのセットアップの人気が高まるにつれ、Firebase Functionsでシンボリックリンクされたパッケージを使用できないことに驚く人が増えると思います。特に、デプロイするまでは正常に機能するためです。
npmがワークスペースのサポートを追加することで、ローカルパッケージがどのように機能するかについてのエコシステム標準があります。
この問題は1年以上前のものですが、Firebase側からの計画(または計画の欠如)に関する更新はありますか?
これはかなり素晴らしい機会だと思います。Firebaseの一連のサービスは、優れたモノレポの設定を求めています。
これに+1すると、クラウド機能は通常、他のアプリといくつかの共通コード(インターフェースなど)を共有する必要があります。これに対処する良い方法は、モノレポ(lernaなど)またはシンボリックリンクを直接使用することです。 私は後者を採用し、いくつかのスクリプトを作成することで解決しました。 概念は非常に簡単です。必要なものをfunctionsディレクトリ内にコピーし、後で削除します。
これが私がこのディレクトリ構造でそれをした方法です:
`` `
content of `pre-deploy.js`
const fs = require( "fs-extra");
const packageJsonPath = "./package.json";
const packageJson = require(packageJsonPath);
(非同期()=> {
fs.remove( ./shared
);を待つ
fs.copy( ../shared
、 ./shared
);を待つ
packageJson.dependencies["@project/shared"] = "file:./shared";
await fs.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2));
})();
content of `post-deploy.js`
const packageJsonPath = "./package.json";
const packageJson = require(packageJsonPath);
const fs = require( "fs-extra");
(非同期()=> {
fs.remove( ./shared
);を待つ
packageJson.dependencies["@project/shared"] = "file:../shared";
await fs.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2));
})();
Then update `firebase.json` like this (add the build script if you need, I build before in my pipeline)
"関数": {
「ソース」:「関数」、
「事前デプロイ」:[
"npm --prefix" $ RESOURCE_DIR "run pre-deploy"
]、
"postdeploy":[
"npm --prefix" $ RESOURCE_DIR "run post-deploy"
]
}、
`` `
ビルドを行う場合、 dist
またはlib
ディレクトリ内に、関数と共有の2つの兄弟があります(これは共有の依存関係のために発生しました)。 デプロイを機能させるには、関数package.json
main
をlib/functions/src/index.js
を指すように更新してください。
今のところ解決されていますが、これは回避策であり、解決策ではありません。 Firebaseツールは本当にシンボリックリンクをサポートする必要があると思います
@michelepatrassiは、このケースを管理するためにfirelink
ライブラリを作成したことを思い出させてくれたことに触発されました。 内部的にrsync
を使用して、再帰ファイルをコピーします。
https://github.com/rxdi/firelink
npm i -g @rxdi/firelink
基本的な使い方
monorepoアプローチがあり、パッケージがpackage.json
が配置されている現在のディレクトリから2レベル下に配置されていると仮定します。
package.json
"fireDependencies": {
"@graphql/database": "../../packages/database",
"@graphql/shared": "../../packages/shared",
"@graphql/introspection": "../../packages/introspection"
},
firelink
実行すると、フォルダに関連するパッケージがコピーされ、既存のパッケージがローカルモジュールインストール"@graphql/database": "file:./.packages/database",
マップされ、コマンドfirebase
が実行され、残りの引数がfirelink
から渡されます。
基本的にfirelink
の代替品であるfirebase
それが生成しますので、CLI firebase
彼の仕事のコピーが終了したら、最後にpackages
し、修正package.json
!
よろしく!
これに噛まれたばかりです。monoreposが標準になり、デフォルトでサポートされるはずです。
みんな、この問題の簡単な解決策は、webpackを使用してクラウド機能をバンドルし、バンドルされたディレクトリからデプロイすることです。 ここに添付されているのは、私が使用している基本的なwebpackファイルです。 ビルド中に、これは、モノリポジトリ内で解決された依存関係を含むすべての関数コードをトップレベルフォルダーにパックします(この場合、そのwebpack/cloud-functions
、それはあなたが構成するものであれば何でもかまいません)
const path = require('path');
module.exports = {
target: 'node',
mode: 'production',
entry: './src/index.ts',
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/
}
]
},
resolve: {
extensions: ['.tsx', '.ts', '.js', '.json']
},
output: {
filename: 'index.js',
path: path.resolve(__dirname, '../../webpack/cloud-functions/dist'),
libraryTarget: 'commonjs'
},
externals: {
'firebase-admin': 'firebase-admin',
'firebase-functions': 'firebase-functions'
}
};
そして最後に、 firebase.json
ファイルで、このフォルダーを参照して展開します。
{
"functions": {
"source": "webpack/cloud-functions"
}
}
webpack/cloud-functions
フォルダーにもpackage.json
ファイルがあることを忘れないでください。
{
"name": "cloud-functions",
"version": "1.0.0",
"scripts": {
"deploy": "firebase deploy --only functions"
},
"engines": {
"node": "10"
},
"main": "dist/index.js",
"dependencies": {
"firebase-admin": "8.9.1",
"firebase-functions": "3.3.0"
},
"devDependencies": {},
"private": true
}
これはテストされ、機能しています。 私はグーグルクラウドビルドを使用しています。 必要に応じて詳細をお尋ねください。
ありがとう、
@sowdri共有してくれてありがとう! firebase.json functions.predeploy
ステップからwebpackビルドをトリガーしますか、それともfirebase deployを呼び出す前にクラウドビルドスクリプトからトリガーしますか?
@ 0x80 cloud build
ステップでビルドしています。 つまり、 firebase cli
によると、これはJSで構築された関数のセットにすぎません。
@sowdri例をありがとう。 AWS Lambdas / Serverlessの過去のプロジェクトで同じアプローチを使用することになりました。ツールを強制的にヤーンモノレポで動作させるよりも、(Webpack)バンドルをアップロードする方が簡単でした。
私もこれに固執しています....関数をデプロイしようとするまで(Firebaseエミュレーターでさえ)すべてが正常に機能しました(reactでビルドされたWebアプリはOKをデプロイします)。 :(Firebaseチームがmonoreposのサポートをすぐに追加できることを願っています。
モノレポの他のパッケージにはbabelを使用しているので、そのままにしておきたいと思います。 他に何もなければ、私はwebpackを試すかもしれません...それはいくつかのために働いているようです。
編集:GitHubパッケージレジストリを使用してこれを解決しました。 そこで、すべてのパッケージをそこで公開してから、 travis
functions
サーバーと.npmrc
介して実行)。 ...エレガントなソリューションのようです。 私はここでこのアプローチのアイデアを得ました: https :
ええ、これにも噛まれました。 firebase serve --only functions
ではすべてが完全に機能しましたが、デプロイするとモジュールを見つけることができませんでした。
結局、パッケージを作成するための小さなスクリプトを作成しました。 これは、モジュールやディレクトリ名と一致するパッケージ名を使用するなど、私の環境の詳細を反映していますが、他の人にも役立つことを願っています。
`` `「fs」からfsをインポートします。
「child_process」からchild_processをインポートします。
const internalPackagesFull = new Map();
//パッケージのすべての部門を検索します
const getDepsForPackage =(packageName)=> {
const packageDir = packageName.split( "/")[1]; //これはあなたのために変更する必要があるかもしれません
const packageSpecFileName = ../${packageDir}/package.json
;
const packageSpecFile = fs.readFileSync(packageSpecFileName);
const packageSpec = JSON.parse(packageSpecFile);
const packageInternalDeps = Object.keys(
packageSpec.dependencies
).filter((key)=> key.includes( "turing")); //これはあなたのために変更する必要があります
const packageTgzName = ${packageName.replace("@", "").replace("/", "-")}-v${
packageSpec.version
}.tgz
;
internalPackagesFull.set(packageName、{
packageSpecFileName、
packageSpec、
packageDir、
packageInternalDeps、
packageTgzName、
});
const packagesToProcess = packageInternalDeps.filter(
(internalDepName)=>!internalPackagesFull.has(internalDepName)
);
packagesToProcess.forEach((internalPackageName)=>
getDepsForPackage(internalPackageName)
);
};
const packageName = JSON.parse(fs.readFileSync( "./ package.json"))。name;
child_process.execSync( cp ./package.json ./package.json.org
);
getDepsForPackage(packageName);
//更新されたパッケージを作成します-一般的なjsを使用し、参照はローカルtgzファイルです
[... internalPackagesFull.values()]。forEach((internalDep)=> {
const {packageSpec、packageSpecFileName、packageInternalDeps} = internalDep;
//パッケージタイプを変更します
packageSpec.type = "commonjs"; //これはあなたのために変更する必要があるかもしれません
//パッケージ化されたzipファイルとなるdepの場所を指定します
packageInternalDeps.forEach((internalDepOfPackage)=> {
const {packageTgzName} = internalPackagesFull.get(internalDepOfPackage);
packageSpec.dependencies [internalDepOfPackage] = ./${packageTgzName}
;
});
fs.writeFileSync(
packageSpecFileName、
JSON.stringify(packageSpec、null、 "")
);
});
//ヤーンビルドとパックを実行します
[... internalPackagesFull.values()]。forEach((internalDep)=> {
試す {
console.log( Buliding ${internalDep.packageDir}
);
child_process.execSync( "yarn build"、{
cwd: ../${internalDep.packageDir}
、
});
console.log( Packaging ${internalDep.packageDir}
);
child_process.execSync( "yarn pack"、{
cwd: ../${internalDep.packageDir}
、
});
if (packageName !== internalDep.packageSpec.name) {
console.log(`Move to current directory ${internalDep.packageDir}`);
child_process.execSync(
`cp ../${internalDep.packageDir}/${internalDep.packageTgzName} .`,
{
cwd: ".",
}
);
}
} catch(e){
console.log(e);
}
});
//標準のパッケージ構造に戻ります
[... internalPackagesFull.values()]
.filter((internalDep)=> packageName!== internalDep.packageSpec.name)
.forEach((internalDep)=> {
const {
packageSpec、
packageSpecFileName、
packageInternalDeps、
} = internalDep;
// change the package type
packageSpec.type = "module"; // THIS MAY NEED TO CHANGE FOR YOU
// specify the location of the dep to be the packaged zip file
packageInternalDeps.forEach((internalDepOfPackage) => {
packageSpec.dependencies[internalDepOfPackage] = "*";
});
fs.writeFileSync(
packageSpecFileName,
JSON.stringify(packageSpec, null, " ")
);
});
`` `
@sowdriが提供するソリューションを使用しました(ありがとうpackage.json
を含むdist/
ディレクトリ全体を自由に削除して再生成できるようにしました。
const path = require('path');
const CopyPlugin = require('copy-webpack-plugin');
module.exports = {
...,
plugins: [
new CopyPlugin({
patterns: [{ from: 'package.dist.json', to: 'package.json' }],
}),
],
};
そして、次のpackage.dist.json
をパッケージルートに保持します。
{
"name": "@package/name",
"version": "0.0.1",
"engines": {
"node": "10"
},
"main": "index.js",
"dependencies": {
"firebase-admin": "8.9.1",
"firebase-functions": "3.3.0"
},
"private": true
}
このファイルから依存関係を削除し、Webpackに依存してそれらをバンドルすることも可能かもしれません(これらの依存関係をメインのpackage.json
と同期させる必要がなくなります)が、私は試していません。
スクリプトを使用して単一のリポジトリを使用し、関連するすべてのディレクトリまたはFirebaseプロジェクトの.firebaserc
とfirebase.json
を、コンパイルされたコードが存在する出力ディレクトリにdir構造を保持するnpmcpyパッケージを使用してコピーします。
関数のデプロイ用に、元のpackage.jsonからpackage.json
を作成します。
これがcopyFiles.js
スクリプトです:
const cpy = require('cpy');
const fs = require('fs');
const package = require('./package.json');
(async () => {
await cpy(['./../package.json', './**/*.json', './**/.firebaserc'], '../out/', {
parents: true,
cwd: 'src'
});
const dirs = fs.readdirSync('./out/');
const newPkg = {
main: package.main,
dependencies: package.dependencies,
engines: package.engines,
}
dirs.forEach(dir => {
fs.writeFileSync(`./out/${dir}/package.json`, JSON.stringify({ name: dir, ...newPkg }));
})
console.log('Files copied!', dirs);
})();
展開するには、 ./out/[project-name]/firebase deploy --only=functions
か、そのためのスクリプトも記述します。
私はこのようないくつかのWebpack警告に遭遇しています:
/Users/me/Development/myproject/node_modules/firebase-functions/lib/config.jsの警告61:23-42
重要な依存関係:依存関係の要求は式です
これらを解決する方法を見つけましたか、それとも無視/抑制していますか?
私は何とか警告なしに物事を動かすことができました🥳私は以下の構成になりました。 特に、外部に正規表現パターンを使用すると、外部に「firebase-functions」がある場合、サブモジュールからのインポートは一致せず、ライブラリはバンドルに含まれるため、違いが生じました。
バンドルの問題の結果として、デプロイ時にいくつかの不可解な@grpcエラーも発生しました。 参考までに保管するのを忘れてしまいました。
const path = require("path");
const CopyPlugin = require("copy-webpack-plugin");
module.exports = {
target: "node",
mode: "production",
entry: "./src/index.ts",
devtool: "inline-source-map",
module: {
rules: [
{
test: /\.tsx?$/,
use: "ts-loader",
exclude: /node_modules/,
},
],
},
resolve: {
extensions: [".tsx", ".ts", ".js", ".json"],
alias: {
"~": path.resolve(__dirname, "src"),
},
},
output: {
filename: "index.js",
path: path.resolve(__dirname, "dist/bundled"),
libraryTarget: "commonjs",
},
externals: ["express", /^firebase.+$/, /^@google.+$/],
plugins: [
new CopyPlugin({
patterns: [{ from: "package.dist.json", to: "package.json" }],
}),
],
};
別のpackage.dist.jsonは必要ないことがわかりました。 もちろん、このファイルがあることの厄介なことは、そこにリストされている依存関係のいずれかを更新するたびに手動で更新する必要があることです。 ですから、それを忘れがちです。
代わりに、package.dist.jsonにリストしないすべてのパッケージをdevDependenciesリストに移動し、そのファイルをwebpackコピープラグインで使用します。 これで、処理するpackage.jsonが1つだけになりました🎉
また、ローカルのnodejsバージョンが関数でデプロイされたノードのバージョンと必ずしも同じである必要はありません。 firebase.jsonファイルでfunctions.runtime
を指定できるようになりました。 そのため、package.jsonからengines
フィールドを取り出し、代わりにFirebase設定でfunctions.runtime
を「10」または「12」に設定します。
これは私にとってそれがどのように見えるかです:
{
"functions": {
"source": "packages/cloud-functions/dist/bundled",
"runtime": "12"
},
"firestore": {
"rules": "firestore.rules",
"indexes": "firestore.indexes.json"
},
"emulators": {
"functions": {
"port": 5001
},
"firestore": {
"port": 8080
},
"pubsub": {
"port": 8085
}
}
}
ソースマップをどのように扱っていますか? devtool: "inline-source-map"
を使用して関数をwebpackにバンドルすると、スタックドライバーのエラーレポートに反映されません。 @sowdri
私は自分のプロジェクトで同じことに遭遇しましたが、サイドプロジェクトのすべてのパッケージを公開したくないので、これはかなり大きな問題でした。 複数のpackage.json
ファイルについていくのは面倒で、パッケージの外でビルドする必要がありました。 オプションとしてdepsを含めると、Lernaは引き続きそれらを取得し、Firebaseはアップロード時に文句を言いません。
以下の設定は、単一のpackage.jsonでシンボリックリンクされたdepサポートを取得します!
package.json
{
"name": "@your-package-name/functions",
"version": "0.1.0",
"scripts": {
"build": "webpack"
},
"engines": {
"node": "10"
},
"main": "dist/index.js",
"dependencies": {
"firebase-admin": "^8.10.0",
"firebase-functions": "^3.6.1"
},
"optionalDependencies": {
"@your-package-name/shared": "^0.1.0",
"@your-package-name/utils": "^0.1.0"
}
}
webpack.config.js
const path = require('path')
// The cost of being fancy I suppose
// https://github.com/firebase/firebase-tools/issues/653
module.exports = {
target: 'node',
mode: 'production',
entry: './src/index.ts',
module: {
rules: [
{
test: /\.tsx?$/,
loader: 'ts-loader',
exclude: /node_modules/,
options: {
configFile: 'tsconfig.build.json',
},
},
],
},
resolve: {
extensions: ['.tsx', '.ts', '.js', '.json'],
},
output: {
filename: 'index.js',
path: path.resolve(__dirname, 'dist'),
libraryTarget: 'commonjs',
},
externals: {
'firebase-admin': 'firebase-admin',
'firebase-functions': 'firebase-functions',
},
}
firebase.json
{
"firestore": {
"rules": "firestore.rules",
"indexes": "firestore.indexes.json"
},
"functions": {
"source": "packages/functions"
},
"emulators": {
"functions": {
"port": 5476
},
"firestore": {
"port": 4565
},
"ui": {
"enabled": true
}
}
}
私はyarnワークスペースを使用していますが、他のpackage.jsonファイルでローカルパッケージ名を指定する必要もありません。 FirebaseとVercelの両方に正常にデプロイしています。
何がそれを機能させるのかわかりません。 私のトップレベルのpackage.jsonにこの標準設定を入れてください:
"workspaces": {
"packages": [
"packages/*"
]
},
yarn upgrade-interactive
を実行すると、すべてを一度に処理できるため、各/ packages / *フォルダーにpackage.jsonを置いてもかまいません。 一部のパッケージでは、そのスコープ専用のスクリプトを追加できると便利です。
- - 編集 - -
プロジェクト参照でTypescriptを使用していることを忘れました。 それはそれと関係があるかもしれません。 Vercelの場合、next-transpile-modulesを使用して、共有コードをバンドルに含めています。
私はこれを機能させるために@ 0x80と@sowdriまでの同様の設定を使用していますが、ローカルの依存関係をdevDependenciesに移動するのではなく(実際には機能しませんでした。ステップが欠落していると思います)、 copy-webpack-plugin
を使用しgenerate-package-json-webpack-plugin
を使用してdistフォルダーにpackage.jsonをビルドしています。 これにより、結果のコードが実際に必要としているものから依存関係リストが作成されるため、バンドルされている場合やdevの依存関係がある場合は、結果のpackage.jsonに含まれません。
また、 webpack-node-externals
を使用して外部を設定し、プロジェクト名のプレフィックスと一致するように正規表現を使用しているシンボリックリンクされたmonorepoパッケージを除くすべてを外部にしました。 追加の外部として投稿されたfirebaseパッケージ@ 0x80の正規表現も追加しました。
これは私の設定です
/* eslint-disable @typescript-eslint/no-var-requires */
const path = require("path");
const nodeExternals = require("webpack-node-externals");
const GeneratePackageJsonPlugin = require("generate-package-json-webpack-plugin");
const basePackage = {
name: "@project/functions",
version: "1.0.0",
main: "./index.js",
scripts: {
start: "yarn run shell"
},
engines: {
node: "12"
}
};
module.exports = {
target: "node",
mode: "production",
entry: "./src/index.ts",
devtool: "inline-source-map",
module: {
rules: [
{
test: /\.tsx?$/,
use: "ts-loader",
exclude: /node_modules/
}
]
},
resolve: {
extensions: [".tsx", ".ts", ".js", ".json"],
alias: {
"@": path.resolve(__dirname, "src"),
"@root": path.resolve(__dirname, "./"),
"@types": path.resolve(__dirname, "src/@types"),
"@utils": path.resolve(__dirname, "src/utils")
}
},
output: {
filename: "index.js",
path: path.resolve(__dirname, "dist"),
libraryTarget: "commonjs"
},
externals: [
/^firebase.+$/,
/^@google.+$/,
nodeExternals({
allowlist: [/^@project/]
})
],
plugins: [new GeneratePackageJsonPlugin(basePackage)]
};
webpackを使用してコードをバンドルすることのもう1つの利点は、最終的にモジュールエイリアスを使用できることです:)
最も参考になるコメント
これに+1すると、クラウド機能は通常、他のアプリといくつかの共通コード(インターフェースなど)を共有する必要があります。これに対処する良い方法は、モノレポ(lernaなど)またはシンボリックリンクを直接使用することです。 私は後者を採用し、いくつかのスクリプトを作成することで解決しました。 概念は非常に簡単です。必要なものをfunctionsディレクトリ内にコピーし、後で削除します。
これが私がこのディレクトリ構造でそれをした方法です:
`` `
| -.firebaserc
| --firebase.json
| -..。
| --src /
| --package.json
| --pre-deploy.js
| --post-deploy.js
| -...。
| --src /
| --package.json
| -...。
const fs = require( "fs-extra");
const packageJsonPath = "./package.json";
const packageJson = require(packageJsonPath);
(非同期()=> {
fs.remove(
./shared
);を待つfs.copy(
../shared
、./shared
);を待つ})();
const packageJsonPath = "./package.json";
const packageJson = require(packageJsonPath);
const fs = require( "fs-extra");
(非同期()=> {
fs.remove(
./shared
);を待つ})();
"関数": {
「ソース」:「関数」、
「事前デプロイ」:[
"npm --prefix" $ RESOURCE_DIR "run pre-deploy"
]、
"postdeploy":[
"npm --prefix" $ RESOURCE_DIR "run post-deploy"
]
}、
`` `
ビルドを行う場合、
dist
またはlib
ディレクトリ内に、関数と共有の2つの兄弟があります(これは共有の依存関係のために発生しました)。 デプロイを機能させるには、関数package.json
main
をlib/functions/src/index.js
を指すように更新してください。今のところ解決されていますが、これは回避策であり、解決策ではありません。 Firebaseツールは本当にシンボリックリンクをサポートする必要があると思います