{"id":1304,"date":"2021-05-13T19:30:00","date_gmt":"2021-05-13T10:30:00","guid":{"rendered":"https:\/\/ito-u-oti.com\/?p=1304"},"modified":"2021-05-24T19:55:31","modified_gmt":"2021-05-24T10:55:31","slug":"react-monorepo","status":"publish","type":"post","link":"https:\/\/ito-u-oti.com\/?p=1304","title":{"rendered":"[React.js]monorepo\u74b0\u5883\u3092\u69cb\u7bc9\u3059\u308b+typescript"},"content":{"rendered":"\n<p>React\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u304c\uff12\u3064\u3042\u308a\u3001\u5171\u901a\u306e\u30e2\u30b8\u30e5\u30fc\u30eb\u3092common\u3068\u3044\u3046\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u3067\u96c6\u7d04\u3057\u3066\u4f7f\u3046\u3053\u3068\u3092\u60f3\u5b9a\u3057\u3066monorepo\u30d9\u30fc\u30b9\u306e\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u3092\u69cb\u7bc9\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" width=\"258\" height=\"240\" src=\"https:\/\/ito-u-oti.com\/wp-content\/uploads\/2021\/05\/image-23.png\" alt=\"\" class=\"wp-image-1306\"\/><\/figure>\n\n\n\n<h2 id=\"outline__1\" class=\"wp-block-heading\">monorepo\u3068\u306f<\/h2>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p>1 \u3064\u306e\u30ea\u30dd\u30b8\u30c8\u30ea\u306e\u4e2d\u306b\u8907\u6570\u306e\u30d1\u30c3\u30b1\u30fc\u30b8\u3092\u540c\u68b1\u3059\u308b\u30ea\u30dd\u30b8\u30c8\u30ea\u306e\u904b\u7528\u65b9\u6cd5<\/p><cite><a href=\"https:\/\/capitalp.jp\/2019\/02\/19\/%E3%83%A2%E3%83%8E%E3%83%AC%E3%83%9D%E5%85%A5%E9%96%80-gutenberg-%E3%81%8C%E6%8E%A1%E7%94%A8%E3%81%99%E3%82%8B%E3%83%AA%E3%83%9D%E3%82%B8%E3%83%88%E3%83%AA%E6%88%A6%E7%95%A5\/\">\u30e2\u30ce\u30ec\u30dd\u5165\u9580 \u2013 Gutenberg \u304c\u63a1\u7528\u3059\u308b\u30ea\u30dd\u30b8\u30c8\u30ea\u6226\u7565<\/a><\/cite><\/blockquote>\n\n\n\n<h2 id=\"outline__2\" class=\"wp-block-heading\">yarn\u3067monorepo\u74b0\u5883\u3092\u69cb\u7bc9\u3059\u308b<\/h2>\n\n\n\n<p>yarn\u3067monorepo\u3092\u4f7f\u3063\u3066\u3044\u304f\u5834\u5408\u306f\u3001<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nyarn workspace\n<\/pre><\/div>\n\n\n<p>\u3092\u4f7f\u3044\u307e\u3059\u3002<\/p>\n\n\n\n<p>subproject\u306b\u30d1\u30c3\u30b1\u30fc\u30b8\u3092\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3059\u308b\u6642\u306f<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nyarn workspace subproject-name add package-name\n<\/pre><\/div>\n\n\n<p>\u3068\u306a\u308a\u307e\u3059\u3002<\/p>\n\n\n\n<h2 id=\"outline__3\" class=\"wp-block-heading\">project\u306e\u4f5c\u6210<\/h2>\n\n\n\n<p>root,subproject\u3092create-react-app\u3067\u4f5c\u3063\u3066\u3044\u304d\u307e\u3059\u3002<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: ; notranslate\" title=\"\">\n# root project\u3092\u4f5c\u308b\nnpm init\n# create-react-app\u3092install\nnpm install create-react-app\n# sub project\u3092\u4f5c\u308b\nnpx create-react-app packages\/project1 --typescript\nnpx create-react-app packages\/project2 --typescript\nnpx create-react-app packages\/common --typescript\n<\/pre><\/div>\n\n\n<h2 id=\"outline__4\" class=\"wp-block-heading\">root project \u306e\u8a2d\u5b9a<\/h2>\n\n\n\n<h3 id=\"outline__4_1\" class=\"wp-block-heading\">\u30eb\u30fc\u30c8\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u306e<code>package.json<\/code>\u3092\u4fee\u6b63<\/h3>\n\n\n\n<p>\u4ee5\u4e0b\u306e\u8a2d\u5b9a\u3092\u8ffd\u52a0\u3057\u307e\u3059\u3002<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n{\n  ...\n  &quot;private&quot;: true,\n  &quot;workspaces&quot;: {\n    &quot;packages&quot;: &#x5B;&quot;packages\/*&quot;],\n    &quot;nohoist&quot;: &#x5B;&quot;**\/react-scripts&quot;, &quot;**\/react-scripts\/**&quot;, &quot;**\/@generated&quot;, &quot;**\/@generated\/*&quot;]\n  }\n  ...\n}\n<\/pre><\/div>\n\n\n<h3 id=\"outline__4_2\" class=\"wp-block-heading\">project \u5171\u901a\u306e<code>tsconfig.json<\/code>\u3092\u30eb\u30fc\u30c8\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u306b\u4f5c\u6210<\/h3>\n\n\n\n<p>tsconfig.json\u3092\u4f5c\u6210\u3057\u307e\u3059\u3002<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n{\n  &quot;compilerOptions&quot;: {\n    &quot;target&quot;: &quot;es5&quot;,\n    &quot;module&quot;: &quot;esnext&quot;,\n    &quot;strict&quot;: true,\n    &quot;esModuleInterop&quot;: true,\n    &quot;forceConsistentCasingInFileNames&quot;: true\n  }\n}\n<\/pre><\/div>\n\n\n<h3 id=\"outline__4_3\" class=\"wp-block-heading\">\u3053\u3053\u307e\u3067<\/h3>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" width=\"257\" height=\"219\" src=\"https:\/\/ito-u-oti.com\/wp-content\/uploads\/2021\/05\/image-24.png\" alt=\"\" class=\"wp-image-1307\"\/><\/figure>\n\n\n\n<h2 id=\"outline__5\" class=\"wp-block-heading\">sub project\u306e\u8a2d\u5b9a\uff08project1,project2\uff09<\/h2>\n\n\n\n<h3 id=\"outline__5_1\" class=\"wp-block-heading\">\u30d1\u30c3\u30b1\u30fc\u30b8\u306e\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb<\/h3>\n\n\n\n<p>monorepo\u5316\u306b\u5fc5\u8981\u306a\u30d1\u30c3\u30b1\u30fc\u30b8\u3092\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3057\u307e\u3059\u3002<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nyarn workspace project1 add react-app-rewired\nyarn workspace project1 add -D customize-cra\n\nyarn workspace project2 add react-app-rewired\nyarn workspace project2 add -D customize-cra\n<\/pre><\/div>\n\n\n<h3 id=\"outline__5_2\" class=\"wp-block-heading\"><code>package.json<\/code>\u4fee\u6b63<\/h3>\n\n\n\n<p>\u4ee5\u4e0b\u306e\u8a2d\u5b9a\u306b\u4fee\u6b63\u3057\u307e\u3059\u3002<br>react-scripts\u306b\u3088\u308b\u5b9f\u884c\u30b3\u30de\u30f3\u30c9\u304b\u3089react-app-rewired\u306b\u3088\u308b\u5b9f\u884c\u306b\u5909\u3048\u3066\u307e\u3059\u3002<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n    ```json\n    {\n      ...\n      &quot;scripts&quot;: {\n        &quot;start&quot;: &quot;react-app-rewired start&quot;,\n        &quot;build&quot;: &quot;react-app-rewired build&quot;\n      }\n      ...\n    }\n    ```\n<\/pre><\/div>\n\n\n<h3 id=\"outline__5_3\" class=\"wp-block-heading\"><code>tsconfig.json<\/code>\u4fee\u6b63<\/h3>\n\n\n\n<p>\u4ee5\u4e0b\u306e\u8a2d\u5b9a\u3092\u8ffd\u52a0\u3057\u307e\u3059\u3002<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n    {\n      &quot;extends&quot;: &quot;.\/tsconfig.path.json&quot;,\n      ...\n    }\n<\/pre><\/div>\n\n\n<h3 id=\"outline__5_4\" class=\"wp-block-heading\"><code>tsconfig.path.json<\/code>\u306e\u4f5c\u6210<\/h3>\n\n\n\n<p>tsconfig.path.json\u3092\u4f5c\u6210\u3057\u307e\u3059\u3002<br>\u5171\u901a\u30e2\u30b8\u30e5\u30fc\u30eb\u7528\u306e\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u3092\u300c@common\u300d\u3068\u3044\u3046\u540d\u524d\u3067\u8a8d\u8b58\u3067\u304d\u308b\u3088\u3046\u306b\u3057\u307e\u3059\u3002<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n    {\n      &quot;extends&quot;: &quot;..\/..\/tsconfig.json&quot;,\n      &quot;compilerOptions&quot;: {\n        &quot;baseUrl&quot;: &quot;.\/&quot;,\n        &quot;paths&quot;: {\n          &quot;@common\/*&quot;: &#x5B;&quot;..\/common\/src\/*&quot;]\n        }\n      }\n    }\n<\/pre><\/div>\n\n\n<h3 id=\"outline__5_5\" class=\"wp-block-heading\"><code>config-overrides.js<\/code>\u306e\u4f5c\u6210<\/h3>\n\n\n\n<p>config-overrides.js\u3092\u4f5c\u6210\u3057\u307e\u3059\u3002<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\n    const { removeModuleScopePlugin, override, babelInclude } = require('customize-cra');\n    const path = require('path');\n\n    function addAlias(config) {\n      config.resolve = {\n        ...config.resolve,\n        alias: { '@common': path.resolve(__dirname, '..\/    common\/src') },\n      };\n      return config;\n    }\n\n    module.exports = override(\n      addAlias,\n\n      \/\/remove limitations of create-react-app\n      removeModuleScopePlugin(),\n      babelInclude(&#x5B;path.resolve('src'), path.resolve('..\/    common\/src')])\n    );\n<\/pre><\/div>\n\n\n<h3 id=\"outline__5_6\" class=\"wp-block-heading\">\u3053\u3053\u307e\u3067\uff08sub project\u306e\u4e2d\uff09<\/h3>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" width=\"261\" height=\"198\" src=\"https:\/\/ito-u-oti.com\/wp-content\/uploads\/2021\/05\/image-25.png\" alt=\"\" class=\"wp-image-1308\"\/><\/figure>\n\n\n\n<h2 id=\"outline__6\" class=\"wp-block-heading\">sub project\u306e\u8a2d\u5b9a\uff08common\uff09<\/h2>\n\n\n\n<p>\u3044\u3089\u306a\u3044\u3082\u306e\u3092\u524a\u3063\u3066\u3044\u304d\u307e\u3059\u3002<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><code>src<\/code>\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u914d\u4e0b\u306e\u30bd\u30fc\u30b9\u5168\u90e8\u6d88\u3059<\/li><li><code>public<\/code>\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u3082\u6d88\u3059<\/li><li><code>create-react-app<\/code>\u30b3\u30de\u30f3\u30c9\u3067\u4f5c\u3089\u308c\u305f\u4e0d\u5fc5\u8981\u306a\u30d5\u30a1\u30a4\u30eb\u3092\u6d88\u3059<\/li><\/ul>\n\n\n\n<p>\u6700\u7d42\u7684\u306b\u6b8b\u308b\u3082\u306e<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><code>src<\/code>\u30c7\u30a3\u30ec\u30af\u30c8\u30ea<\/li><li><code>package.json<\/code><\/li><li><code>readme.json<\/code><\/li><li><code>tsconfig.json<\/code><\/li><\/ul>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" width=\"217\" height=\"134\" src=\"https:\/\/ito-u-oti.com\/wp-content\/uploads\/2021\/05\/image-26.png\" alt=\"\" class=\"wp-image-1309\"\/><\/figure>\n\n\n\n<h2 id=\"outline__7\" class=\"wp-block-heading\">\u5f8c\u59cb\u672b<\/h2>\n\n\n\n<p>\u5404 project \u306e<code>node_modules<\/code>\u3068<code>yarn.lock<\/code>\u3092\u6d88\u3057\u3066\u518d\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3057\u76f4\u3057\u3066\u304a\u304d\u307e\u3059\u3002<\/p>\n\n\n\n<p>\u3053\u308c\u3067monorepo\u74b0\u5883\u306e\u69cb\u7bc9\u306f\u5b8c\u4e86\u3067\u3059\u3002<\/p>\n\n\n\n<h2 id=\"outline__8\" class=\"wp-block-heading\">common\u306e\u30bd\u30fc\u30b9\u3092sub project\u3067\u4f7f\u3046<\/h2>\n\n\n\n<h3 id=\"outline__8_1\" class=\"wp-block-heading\">common project \u306b\u5171\u901a\u7684\u306b\u4f7f\u3044\u305f\u3044\u30d5\u30a1\u30a4\u30eb\u3092\u4f5c\u308b<\/h3>\n\n\n\n<p><code>common\/src\/Hello.tsx<\/code><\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\n    import React, { ReactElement } from 'react';\n\n    interface Props {}\n\n    function Hello({}: Props): ReactElement {\n      return &lt;div&gt;view from Common packages!&lt;\/div&gt;;\n    }\n    export default Hello;\n<\/pre><\/div>\n\n\n<h3 id=\"outline__8_2\" class=\"wp-block-heading\">sub project \u5185\u3067 import \u3059\u308b<\/h3>\n\n\n\n<p><code>import Hello from '@common\/Hello'<\/code>\u3067 import<br><code>project1\/src\/app.tsx<\/code><\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\n    import React from 'react';\n    import logo from '.\/logo.svg';\n    import '.\/App.css';\n    import Hello from '@common\/Hello';\n\n    function App() {\n      return (\n        &lt;div className='App'&gt;\n          &lt;header className='App-header'&gt;\n            &lt;img src={logo} className='App-logo' alt='logo' \/&gt;\n            &lt;p&gt;\n              Edit &lt;code&gt;src\/App.tsx&lt;\/code&gt; and save to reload.\n            &lt;\/p&gt;\n            &lt;a className='App-link' href='https:\/\/reactjs.org' target='_blank' rel='noopener noreferrer'&gt;\n              Learn React\n            &lt;\/a&gt;\n            &lt;Hello&gt;&lt;\/Hello&gt;\n          &lt;\/header&gt;\n        &lt;\/div&gt;\n      );\n    }\n\n    export default App;\n<\/pre><\/div>\n\n\n<h3 id=\"outline__8_3\" class=\"wp-block-heading\">yarn start<\/h3>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nyarn workspace project1 start\n<\/pre><\/div>\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" width=\"650\" height=\"539\" src=\"https:\/\/ito-u-oti.com\/wp-content\/uploads\/2021\/05\/image-27.png\" alt=\"\" class=\"wp-image-1310\"\/><\/figure>\n\n\n\n<p>\u4e0b\u6bb5\u306bcommon\u30e2\u30b8\u30e5\u30fc\u30eb\u306b\u4f5c\u6210\u3057\u305f Helllo.tsx \u306e\u300cview from Common packages!\u300d\u304c\u8868\u793a\u3055\u308c\u3066\u3044\u307e\u3059\u3002<\/p>\n\n\n\n<h2 id=\"outline__9\" class=\"wp-block-heading\">\u95a2\u9023<\/h2>\n\n\n\n<p><a href=\"https:\/\/ito-u-oti.com\/react-monorepo\/\"><a href=\"https:\/\/ito-u-oti.com\/sonarqube-react-monorepo\/\">SonarQube\u3068project\u306e\u9023\u643a\u65b9\u6cd5(monorepo+React + TypeScript)<\/a><\/a><\/p>\n\n\n\n<h2 id=\"outline__10\" class=\"wp-block-heading\">\u53c2\u8003<\/h2>\n\n\n\n<p><a href=\"https:\/\/qiita.com\/suzukalight\/items\/0b22f11ad05308f638a6\">yarn workspace\u3067monorepo+TypeScript+Lint\u74b0\u5883\u3092\u3064\u304f\u308b<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>React\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u304c\uff12\u3064\u3042\u308a\u3001\u5171\u901a\u306e\u30e2\u30b8\u30e5\u30fc\u30eb\u3092common\u3068\u3044\u3046\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u3067\u96c6\u7d04\u3057\u3066\u4f7f\u3046\u3053\u3068 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":1314,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[298],"tags":[297,295,296,283],"class_list":["post-1304","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-react-js","tag-monorepo","tag-react-js","tag-typescript","tag-yarn"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/ito-u-oti.com\/index.php?rest_route=\/wp\/v2\/posts\/1304","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ito-u-oti.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/ito-u-oti.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/ito-u-oti.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/ito-u-oti.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1304"}],"version-history":[{"count":5,"href":"https:\/\/ito-u-oti.com\/index.php?rest_route=\/wp\/v2\/posts\/1304\/revisions"}],"predecessor-version":[{"id":1337,"href":"https:\/\/ito-u-oti.com\/index.php?rest_route=\/wp\/v2\/posts\/1304\/revisions\/1337"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/ito-u-oti.com\/index.php?rest_route=\/wp\/v2\/media\/1314"}],"wp:attachment":[{"href":"https:\/\/ito-u-oti.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1304"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ito-u-oti.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1304"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ito-u-oti.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1304"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}