フルスタックのJavaScriptのmonorepoの例
32766 ワード
あなたは大きなJavaScriptプロジェクトに取り組んでいます.それは機能でいっぱいで、日によって成長しています.
あなたはフロントエンドやサービスのバックエンド側の任意の種類のWebとモバイルクライアントを持っている.
あなたのアプリケーションのすべての部分はどういうわけか、他の部分と連携して、開発段階でプロジェクトを開始することもできます.
それがそうであるならば、私がMonoreposについて言わなければならないものを聞きます.
( source code )
ASWikipedia says :
シンプルで簡単.
JavaScriptの典型的な構造は以下の通りです:
JavaScriptが付属しているとき、私たちは一つのリポジトリ内のプロジェクトを管理するために少なくとも2つのツールを持っています.
Yarn は、よく知られている依存関係管理ツール(NPMに相当)です.また、マルチパッケージ管理のプリミティブを提供することにより、プロジェクト管理ツールworkspaces :
基本的にこれらの機能を使用して、我々は単一の糸があります.ロックとルートレベルでの単一のNodeThangモジュールフォルダは、すべてのプロジェクト依存関係が一緒にインストールされることを意味します.
さらに、内部のパッケージ間の依存関係を定義することができます.
Lerna サブプロジェクトの特定のセットとリポジトリで変更されたものに基づいてバージョン管理とパッケージパブリッシングのための統合された解決にカスタムスクリプトを実行する能力などのユーティリティを提供します.
完全性のために、それは糸のワークスペースだけでなく、それらを統合する可能性によってネイティブに実装されたすべての機能を提供しています:我々は第2のオプションを選択します.
糸、ラーナとmonoreposのより徹底的な議論のために、私はこの素晴らしいことを勧めますarticle .
私たちのサンプルプロジェクトは、バックエンドからいくつかの本をフェッチし、Webインターフェイスを介して表示されるおもちゃのアプリケーションです.
しかし、それを実装するには、以下のようなアーキテクチャを選びました. これは、マイクロサービスアーキテクチャ、特にフロントエンドとバックエンドは2つの別々のアプリケーションです. また、複数のアプリケーションで共有できるパッケージを作成する可能性もあります. 簡単に少なくとも1つの現実世界のユースケースをカバーするために強化することができますStorybook Design System Architecture )
アプリケーションとパッケージの2つの別個のフォルダにプロジェクトを分割します.
アプリケーションフォルダには、実行時にアプリケーションを構成するすべてのコンポーネントが含まれます.
パッケージフォルダには、我々のアプリケーションによって共有されるモジュールが含まれます.
最終的なフォルダ構造は次のようになります.
まず、Monorepoの管理ツールを設定する必要があります.
ルートの内部:
それから、Lernaをインストールしなければなりません.
次に我々のプロジェクト構造に従って糸のワークスペースを定義します.
バックエンドのために、私はGraphSQLを選びました.特に、私たちはgetting started tutorial of the official apollo website ( JavaScript ES 6の構文を利用するバベルを追加しました).
まず最初に新しいディレクトリとcdを作ります.
ここでは、GraphSQLアプリケーションを起動するスクリプトを定義します.
クライアント側のために、我々はGraphSQLバックエンドで働くためにアポロクライアントで反応ウェブアプリケーションを構築するつもりです.
まず最初に、新しいCRAプロジェクトをブートストラップします.
ここではいくつかの反応コンポーネントをパッケージ化します.
まず最初に新しいディレクトリとcdを作ります.
我々のアプリは、そのような複雑なアーキテクチャが完全に不当に見えるかもしれないほど簡単です.
しかし、この方法を考えてください.あなたは世界で最高のオンライン書店になるこの本のリストアプリをしたい!
クライアント側では、少なくともあなたの顧客のためのストアアプリケーションとあなたのためのダッシュボードを供給する必要があります.
サーバー側でデータモデルの下に爆発します.あなたのユーザー、トラックの注文などを管理する必要があります.つまり、サードパーティのシステムには、おそらくコードのビジネスロジックラインのトンを書き込む必要があります.あなたのコードを通して低結合と高い結合の原則を維持するために、あなたは多くのアプリケーションとモジュールの向こう側にこれらの論理を分割する必要があります.
あなたのアプリはおそらく次のようになります.
提案されたMonorepo構造によれば、あなたのコードを管理可能にしている間、プロジェクトをスケールアップするのは簡単です.適切なフォルダの下に必要なすべての新しいパッケージおよび/またはアプリケーションを作成するだけです.
Web開発の分野におけるJavaScriptの破壊的な上昇は、単一のプログラミング言語で非常に複雑なアプリケーションを開発することが可能な技術の現状に達している.
この状況は、ここで部分的に記述されたプロジェクト管理の集中化の可能性のようないくつかの利点を提供します.
私はこの問題に関する私の考えがあなたの現在または次のプロジェクトへの助けとなることを心から願っています.
フィードバックの任意の並べ替えは非常に有り難いです!
あなたはフロントエンドやサービスのバックエンド側の任意の種類のWebとモバイルクライアントを持っている.
あなたのアプリケーションのすべての部分はどういうわけか、他の部分と連携して、開発段階でプロジェクトを開始することもできます.
それがそうであるならば、私がMonoreposについて言わなければならないものを聞きます.
( source code )
モノレールは何ですか。
ASWikipedia says :
A monorepo is a software development strategy
where code for many projects is stored in the same
repository.
シンプルで簡単.
JavaScriptの典型的な構造は以下の通りです:
repo-root/
package.json
projects/
project-1/
package.json
project-2/
package.json
工具
JavaScriptが付属しているとき、私たちは一つのリポジトリ内のプロジェクトを管理するために少なくとも2つのツールを持っています.
糸
Yarn は、よく知られている依存関係管理ツール(NPMに相当)です.また、マルチパッケージ管理のプリミティブを提供することにより、プロジェクト管理ツールworkspaces :
Workspaces are a new way to set up your package architecture that’s
available by default starting from Yarn 1.0. It allows you to setup
multiple packages in such a way that you only need to runyarn
once to install all of them in a single pass.
install
基本的にこれらの機能を使用して、我々は単一の糸があります.ロックとルートレベルでの単一のNodeThangモジュールフォルダは、すべてのプロジェクト依存関係が一緒にインストールされることを意味します.
さらに、内部のパッケージ間の依存関係を定義することができます.
ラーナ
A tool for managing JavaScript projects with multiple packages.
Lerna サブプロジェクトの特定のセットとリポジトリで変更されたものに基づいてバージョン管理とパッケージパブリッシングのための統合された解決にカスタムスクリプトを実行する能力などのユーティリティを提供します.
完全性のために、それは糸のワークスペースだけでなく、それらを統合する可能性によってネイティブに実装されたすべての機能を提供しています:我々は第2のオプションを選択します.
糸、ラーナとmonoreposのより徹底的な議論のために、私はこの素晴らしいことを勧めますarticle .
サンプルプロジェクト
私たちのサンプルプロジェクトは、バックエンドからいくつかの本をフェッチし、Webインターフェイスを介して表示されるおもちゃのアプリケーションです.
しかし、それを実装するには、以下のようなアーキテクチャを選びました.
フォルダ構造
アプリケーションとパッケージの2つの別個のフォルダにプロジェクトを分割します.
アプリケーションフォルダには、実行時にアプリケーションを構成するすべてのコンポーネントが含まれます.
パッケージフォルダには、我々のアプリケーションによって共有されるモジュールが含まれます.
最終的なフォルダ構造は次のようになります.
repo-root/
package.json
packages/
design-system/
package.json
applications/
client/
package.json
api/
package.json
糸/ Lernaセットアップ
まず、Monorepoの管理ツールを設定する必要があります.
ルートの内部:
yarn init
注意:糸のワークスペースはルートパッケージを必要とします.JSONはプライベートなので、糸の初期化過程では、プライベートフラグをtrueに設定してください.それから、Lernaをインストールしなければなりません.
yarn add lerna -D
yarn lerna init
私は常に依存関係のこの種の依存関係をインストールすることを好む.次に我々のプロジェクト構造に従って糸のワークスペースを定義します.
// package.json
{
…
"private": true,
"workspaces": [
"applications/*",
"packages/*"
],
…
}
次に、我々はLearnaに糸のワークスペースとの統合を指示する.// lerna.json
{
...
"packages": [
"applications/*",
"packages/*"
],
"npmClient": "yarn",
"useWorkspaces": true,
...
}
最後に、開発中にアプリケーションを起動するためのカスタムスクリプトを追加します.// package.json
{
…
"scripts": {
"start": "yarn lerna run development:start --parallel"
},
…
}
APIアプリケーションのコーディング
バックエンドのために、私はGraphSQLを選びました.特に、私たちはgetting started tutorial of the official apollo website ( JavaScript ES 6の構文を利用するバベルを追加しました).
まず最初に新しいディレクトリとcdを作ります.
mkdir -p applications/api
cd applications/api
プロジェクトの依存関係を初期化しなければなりませんyarn init -y
yarn workspace applications/api add @babel/core @babel/cli @babel/node @babel/preset-env nodemon -D
yarn add apollo-server graphql
yarn install
ファイルとフォルダmkdir src
touch src/index.js
touch .babelrc
次にいくつかの設定を加えなければなりません.ここでは、GraphSQLアプリケーションを起動するスクリプトを定義します.
// applications/api/package.json
{
...
"scripts": {
...
"development:start": "yarn nodemon --exec babel-node src/index.js ",
...
},
...
}
ここでは、Babelコンパイラのプリセットを定義します.// applications/api/.babelrc
{
"presets": ["@babel/preset-env"]
}
最後にコードを追加できます:// applications/api/src/index.js
import { ApolloServer, gql } from "apollo-server";
const typeDefs = gql`
type Book {
title: String
author: String
}
type Query {
books: [Book]
}
`;
const books = [
{
title: "Harry Potter and the Chamber of Secrets",
author: "J.K. Rowling"
},
{
title: "Jurassic Park",
author: "Michael Crichton"
}
];
const resolvers = {
Query: {
books: () => books
}
};
const server = new ApolloServer({ typeDefs, resolvers });
server.listen().then(({ url }) => {
console.log(`🚀 Server ready at ${url}`);
});
これで次のように動作します.yarn development:start
orcd ../..
yarn start
クライアントアプリケーションのコーディング
クライアント側のために、我々はGraphSQLバックエンドで働くためにアポロクライアントで反応ウェブアプリケーションを構築するつもりです.
まず最初に、新しいCRAプロジェクトをブートストラップします.
npx create-react-app applications/client
我々は1つだけ糸を覚えている.ロックとそれがルートレベルに置かれなければならないので、craが糸を作成しないことを確認してください.ロック.そうでない場合:rm applications/client/yarn.lock
次に依存関係をインストールします.cd applications/client
yarn add @apollo/client graphql
次にいくつかの設定を追加します.// applications/client/package.json
{
...
"scripts": {
"development:start": "CI=true yarn react-scripts start",
...
}
...
}
最後に、コードを追加します.// applications/client/src/App.js
import React from "react";
import { ApolloClient, ApolloProvider, InMemoryCache } from "@apollo/client";
import Books from "./components/Books";
const client = new ApolloClient({
uri: "http://localhost:4000",
cache: new InMemoryCache()
});
function App() {
return (
<ApolloProvider client={client}>
<Books />
</ApolloProvider>
);
}
export default App;
ここで我々のアプリのコンテンツを作成している:mkdir src/components
touch src/components/Books.js
// applications/client/src/components/Books.js
import React from "react";
import { useQuery, gql } from "@apollo/client";
const ALL_BOOKS = gql`
query GetAllBooks {
books {
title
author
}
}
`;
function Books() {
const { loading, error, data } = useQuery(ALL_BOOKS);
if (loading) return <p>Loading...</p>;
if (error) return <p>Error :(</p>;
return data.books.map(({ title, author }) => (
<div key={title}>
<p>
{title} by {author}
</p>
</div>
));
}
export default Books;
実行してテストします.cd ../..
yarn start
APIアプリケーションも起動する方法に注意してください.デザインシステムパッケージのコーディング
ここではいくつかの反応コンポーネントをパッケージ化します.
まず最初に新しいディレクトリとcdを作ります.
mkdir -p packages/design-system
cd packages/design-system
それから我々はプロジェクトとその構造をinitしなければならない.yarn init -y
yarn add react@^16.0.0 -P
yarn add microbundle-crl -D
mkdir src
touch src/index.js
mkdir src/components
touch src/components/List.js
touch src/components/ListItem.js
次にいくつかの設定を追加します.// packages/design-system/package.json
{
...
"main": "dist/index.js",
"module": "dist/index.modern.js",
"source": "src/index.js",
"scripts": {
...
"development:start": "yarn microbundle-crl watch --no-compress --format modern,cjs"
...
},
...
}
最後に、コードを追加します.// packages/design-system/src/index.js
import List from "./components/List";
export { List };
// packages/design-system/src/components/ListItem.js
import React from "react";
import PropTypes from "prop-types";
// I'm not using css files because they will not work when exported!
// Consider to use styled components for your project...
function ListItem(props) {
return (
<div
style={{
margin: "10px",
padding: "10px",
border: "1px solid #bbb",
backgroundColor: "#eee"
}}
>
<span
style={{
fontSize: "1.2em",
textDecoration: "none",
color: "#333"
}}
>
{props.text}
</span>
</div>
);
}
ListItem.propTypes = {
text: PropTypes.string.isRequired
};
export default ListItem;
// packages/design-system/src/components/List.js
import React from "react";
import PropTypes from "prop-types";
import ListItem from "./ListItem";
function List(props) {
return (
<div>
{props.items.map((content, index) => (
<ListItem key={index} text={content || ""} />
))}
</div>
);
}
List.propTypes = {
items: PropTypes.arrayOf(PropTypes.string).isRequired
};
export default List;
最後のステップとしてクライアントアプリケーションを更新する必要があります.// applications/client/src/components/Books.js
import React from "react";
import { useQuery, gql } from "@apollo/client";
import { List } from "design-system";
const ALL_BOOKS = gql`
query GetAllBooks {
books {
title
author
}
}
`;
function Books() {
const { loading, error, data } = useQuery(ALL_BOOKS);
if (loading) return <p>Loading…</p>;
if (error) return <p>Error :(</p>;
return (
<List
items={data.books.map(({ title, author }) => `${title} by ${author}`)}
/>
);
}
export default Books;
と依存関係:yarn add design-system@^1.0.0
これで、最終的なアプリケーションをテストすることができますcd ../..
yarn start
注:現在のところ、反応の開発サーバーのバグがあるようです.最初の開始後、ページを更新する必要があります.改善の余地
我々のアプリは、そのような複雑なアーキテクチャが完全に不当に見えるかもしれないほど簡単です.
しかし、この方法を考えてください.あなたは世界で最高のオンライン書店になるこの本のリストアプリをしたい!
クライアント側では、少なくともあなたの顧客のためのストアアプリケーションとあなたのためのダッシュボードを供給する必要があります.
サーバー側でデータモデルの下に爆発します.あなたのユーザー、トラックの注文などを管理する必要があります.つまり、サードパーティのシステムには、おそらくコードのビジネスロジックラインのトンを書き込む必要があります.あなたのコードを通して低結合と高い結合の原則を維持するために、あなたは多くのアプリケーションとモジュールの向こう側にこれらの論理を分割する必要があります.
あなたのアプリはおそらく次のようになります.
提案されたMonorepo構造によれば、あなたのコードを管理可能にしている間、プロジェクトをスケールアップするのは簡単です.適切なフォルダの下に必要なすべての新しいパッケージおよび/またはアプリケーションを作成するだけです.
結論
Web開発の分野におけるJavaScriptの破壊的な上昇は、単一のプログラミング言語で非常に複雑なアプリケーションを開発することが可能な技術の現状に達している.
この状況は、ここで部分的に記述されたプロジェクト管理の集中化の可能性のようないくつかの利点を提供します.
私はこの問題に関する私の考えがあなたの現在または次のプロジェクトへの助けとなることを心から願っています.
フィードバックの任意の並べ替えは非常に有り難いです!
Reference
この問題について(フルスタックのJavaScriptのmonorepoの例), 我々は、より多くの情報をここで見つけました https://dev.to/alecap7/have-you-ever-heard-of-javascript-monorepos-here-is-an-example-3g7mテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol