{"id":3677,"date":"2021-05-14T16:27:07","date_gmt":"2021-05-14T16:27:07","guid":{"rendered":"https:\/\/ionicframework.com\/blog\/?p=3677"},"modified":"2021-05-14T16:27:07","modified_gmt":"2021-05-14T16:27:07","slug":"monorepos-with-ionic-vue-and-npm","status":"publish","type":"post","link":"https:\/\/ionic.io\/blog\/monorepos-with-ionic-vue-and-npm","title":{"rendered":"Monorepos with Ionic, Vue, and npm"},"content":{"rendered":"<blockquote><p>\n  This is part three of a <a href=\"https:\/\/ionicframework.com\/blog\/understanding-monorepos\/\">new series on monorepos<\/a>. By the end of the series, you&#8217;ll have the tools you need to adopt monorepo setups in your organization.\n<\/p><\/blockquote>\n<p>Rounding out our series on monorepos, we take a look at an old friend, but a newcomer to the monorepo game, npm. Npm has long been the de-facto solution for managing dependencies, and it only makes sense that, with the release of npm 7.0, we finally have a built-in solution for creating a monorepo without relying on external tools. Compared to other solutions, however, npm workspaces lack a few features and still have some rough edges. While it is possible to build something with it, for simplicity, I\u2019d suggest looking at Lerna as an alternative. With that being said, let&#8217;s look at how we can configure an npm workspace to work with Ionic and Vue.<\/p>\n<p><!--more--><\/p>\n<h2>Scaffolding<\/h2>\n<p>To set the scene, what we\u2019re going to build is an Ionic Vue app and a second project that contains a Vue hook. The hook is borrowed from the <a href=\"https:\/\/github.com\/pikax\/vue-composable\">vue-composable<\/a> project.<\/p>\n<p>Let&#8217;s get started by first creating our base directory and initializing both a <code>package.json<\/code> and an <code>ionic.config.json<\/code>. For the <code>package.json<\/code>, run:<\/p>\n<pre><code class=\"language-shell\">mkdir vue-monorepo\ncd vue-monorepo\nnpm init -y\n<\/code><\/pre>\n<p>From here, we can also create a base Ionic project with the <code>ionic init<\/code> command.<\/p>\n<pre><code class=\"language-shell\">ionic init --multi-app\n<\/code><\/pre>\n<p>We can also create a directory that will hold all the packages. For this, a directory called <code>packages<\/code> will do, but the name can be whatever you\u2019d like. <code>packages<\/code> is just a common convention that people have settled around.<\/p>\n<pre><code class=\"language-shell\">mkdir packages\ncd packages\n<\/code><\/pre>\n<p>With this done, we&#8217;re going to create a single Ionic Vue project and a minimal utility package.<\/p>\n<pre><code class=\"language-shell\">mkdir utils\nionic start client-app tabs --type vue --no-deps --no-git\n<\/code><\/pre>\n<blockquote><p>\n  Currently, even if you pass the <code>--no-deps<\/code> flag, dependencies will be installed when Capacitor is set up. Just <code>cd client-app<\/code> and delete the node_modules folder from the project.\n<\/p><\/blockquote>\n<h3>Setting up the Utils<\/h3>\n<p>For our <code>utils<\/code> package, we&#8217;re going to do a bit more manual work to set up a minimal package of hooks for our Vue project.<\/p>\n<pre><code class=\"language-shell\">cd packages\/utils\nnpm init -y\nmkdir src\ntouch tsconfig.json\n<\/code><\/pre>\n<p>Open your <code>package.json<\/code> and paste the following:<\/p>\n<pre><code class=\"language-json\">{\n  &quot;name&quot;: &quot;@client\/hooks&quot;,\n  &quot;version&quot;: &quot;0.1.0&quot;,\n  &quot;private&quot;: true,\n  &quot;main&quot;: &quot;dist\/index.js&quot;,\n  &quot;module&quot;: &quot;dist\/index.js&quot;,\n  &quot;scripts&quot;: {\n    &quot;build&quot;: &quot;tsc -p tsconfig.json&quot;,\n    &quot;watch&quot;: &quot;tsc -p tsconfig.json --watch&quot;\n  },\n  &quot;dependencies&quot;: {\n    &quot;vue&quot;: &quot;^3.0.0&quot;\n  },\n  &quot;files&quot;: [&quot;dist\/&quot;],\n  &quot;devDependencies&quot;: {\n    &quot;typescript&quot;: &quot;~4.1.5&quot;\n  }\n}\n<\/code><\/pre>\n<p>Then, open your <code>tsconfig.json<\/code> and paste the following:<\/p>\n<pre><code class=\"language-json\">{\n  &quot;compilerOptions&quot;: {\n    &quot;target&quot;: &quot;ES5&quot;,\n    &quot;outDir&quot;: &quot;dist&quot;,\n    &quot;module&quot;: &quot;CommonJS&quot;,\n    &quot;strict&quot;: true,\n    &quot;importHelpers&quot;: true,\n    &quot;moduleResolution&quot;: &quot;node&quot;,\n    &quot;skipLibCheck&quot;: true,\n    &quot;esModuleInterop&quot;: false,\n    &quot;declaration&quot;: true,\n    &quot;allowSyntheticDefaultImports&quot;: true,\n    &quot;sourceMap&quot;: true,\n    &quot;lib&quot;: [&quot;esnext&quot;, &quot;dom&quot;, &quot;dom.iterable&quot;]\n  },\n  &quot;include&quot;: [&quot;src\/**\/*.ts&quot;],\n  &quot;exclude&quot;: [&quot;node_modules&quot;]\n}\n<\/code><\/pre>\n<p>From here, we can make a file, <code>src\/index.ts<\/code>, and paste the following code.<\/p>\n<pre><code class=\"language-ts\">\/* eslint-disable *\/\nimport { ref, Ref } from &#039;vue&#039;;\n\n\/\/ useOnline composable hook.\n\/\/ Adapted from https:\/\/github.com\/pikax\/vue-composable\n\nconst PASSIVE_EV: AddEventListenerOptions = { passive: true };\nlet online: Ref&lt;boolean&gt; | undefined = undefined;\nexport function useOnline() {\n  const supported = &#039;onLine&#039; in navigator;\n  if (!supported) {\n    online = ref(false);\n  }\n\n  if (!online) {\n    online = ref(navigator.onLine);\n    window.addEventListener(\n      &#039;offline&#039;,\n      () =&gt; (online!.value = false),\n      PASSIVE_EV\n    );\n    window.addEventListener(&#039;online&#039;, () =&gt; (online!.value = true), PASSIVE_EV);\n  }\n\n  return { supported, online };\n}\n<\/code><\/pre>\n<p>Now we can leave the <code>utils<\/code> directory and get back to the root project.<\/p>\n<h2>Setting up the Workspace<\/h2>\n<p>With the initial code created, we can now set up the workspace. For npm, workspaces are just an entry in the root <code>package.json<\/code>. Since all of our packages are in the <code>packages<\/code> directory, we can add the following to the root <code>package.json<\/code>.<\/p>\n<pre><code class=\"language-json\">{\n  &quot;name&quot;: &quot;ionic-vue-npm-workspaces&quot;,\n  &quot;version&quot;: &quot;1.0.0&quot;,\n  &quot;description&quot;: &quot;&quot;,\n  &quot;scripts&quot;: {...},\n  &quot;license&quot;: &quot;MIT&quot;,\n\n  &quot;workspaces&quot;: [\n    &quot;packages\/*&quot;\n  ]\n\n}\n<\/code><\/pre>\n<p>The <code>workspaces<\/code> entry allows us to declare what packages are available from this top level. Since we want to expose all packages in the <code>packages<\/code> directory, we can use the <code>packages\/*<\/code> to get all of them.<\/p>\n<p>With this completed, run <code>npm install<\/code> from the top level. With our workspace set up to include all the sub-packages, our install will actually install <em>all<\/em> dependencies used in both projects in one top-level <code>node_modules<\/code> directory. This means we can have better control over what dependencies we are using in which project and unifies all duplicated dependencies to one version.<\/p>\n<p>With the dependencies installed, how do we go about actually building our sub-packages? This can be done by calling the script we want to run, followed by the <code>--workspace=&lt;package-name&gt;<\/code>. If we want to build the <code>utils<\/code> directory, we use the name entry from the package.json (<code>@client\/hooks<\/code>) as the value for the workspace. So our final command looks like this:<\/p>\n<pre><code class=\"language-shell\">npm run build --workspace=@client\/hooks\n<\/code><\/pre>\n<p>The same logic would be applied if we want to build\/serve our app: we pick the script we want to run and pass the name to the workspace.<\/p>\n<h2>Including a Package<\/h2>\n<p>So far, we have our packages set up and building, but we&#8217;re not making use of them, which kind of defeats the point of having a monorepo. So how can we consume our utils packages in our main app? To do this, we\u2019ll reference the package in our app.<\/p>\n<p>In the <code>client-app<\/code> project, let&#8217;s open our <code>package.json<\/code> and add a line to our dependencies for <code>@client\/hooks<\/code>:<\/p>\n<pre><code class=\"language-json\">{\n  &quot;dependencies&quot;: {\n    &quot;@capacitor\/core&quot;: &quot;3.0.0-rc.1&quot;,\n    &quot;@client\/hooks&quot;: &quot;0.1.0&quot;,\n    &quot;@ionic\/vue&quot;: &quot;^5.4.0&quot;,\n    &quot;@ionic\/vue-router&quot;: &quot;^5.4.0&quot;,\n    &quot;core-js&quot;: &quot;^3.6.5&quot;,\n    &quot;vue&quot;: &quot;^3.0.0-0&quot;,\n    &quot;vue-router&quot;: &quot;^4.0.0-0&quot;\n  }\n}\n<\/code><\/pre>\n<p>Then we can add a reference to <code>@client\/hooks<\/code> in our project in the <code>client-app\/src\/views\/Tab1.vue<\/code> component.<\/p>\n<pre><code class=\"language-html\">&lt;template&gt;\n  &lt;ion-page&gt;\n    &lt;ion-header&gt;\n      &lt;ion-toolbar&gt;\n        &lt;ion-title&gt;Tab 1&lt;\/ion-title&gt;\n      &lt;\/ion-toolbar&gt;\n    &lt;\/ion-header&gt;\n    &lt;ion-content :fullscreen=&quot;true&quot;&gt;\n      &lt;ion-header collapse=&quot;condense&quot;&gt;\n        &lt;ion-toolbar&gt;\n          &lt;ion-title size=&quot;large&quot;&gt;Tab 1&lt;\/ion-title&gt;\n        &lt;\/ion-toolbar&gt;\n      &lt;\/ion-header&gt;\n        &lt;h1&gt;Is the App online?&lt;\/h1&gt;\n        &lt;p&gt;{{ online }}&lt;\/p&gt;\n      &lt;ExploreContainer name=&quot;Tab 1 page&quot; \/&gt;\n    &lt;\/ion-content&gt;\n  &lt;\/ion-page&gt;\n&lt;\/template&gt;\n\n&lt;script lang=&quot;ts&quot;&gt;\nimport { IonPage, IonHeader, IonToolbar, IonTitle, IonContent } from &#039;@ionic\/vue&#039;;\nimport ExploreContainer from &#039;@\/components\/ExploreContainer.vue&#039;;\n\nimport { useOnline } from &#039;@client\/hooks&#039;;\n\nexport default  {\n  name: &#039;Tab1&#039;,\n  components: { ExploreContainer, IonHeader, IonToolbar, IonTitle, IonContent, IonPage },\n    setup() {\n    const { online } = useOnline();\n    return { online };\n  },\n\n}\n&lt;\/script&gt;\n<\/code><\/pre>\n<p>We can save and go back to the terminal, and from the root, run:<\/p>\n<pre><code class=\"language-shell\">npm install\nnpm run serve --workspace=client-app\n<\/code><\/pre>\n<p>When we open the browser to <code>localhost:8080<\/code>, our app should include the code from our second package.<\/p>\n<h2>Parting Thoughts<\/h2>\n<p>Of all of the options available, npm workspaces include the fewest features when compared to yarn\/Lerna or nx. But that could be beneficial to you and your team if you want to have more control over how your monorepos work. This could be perfect for a team that likes to tinker with things, or wants to assemble their own monorepo infrastructure. Either way, it\u2019s great to see npm enter the monorepo game, and we can\u2019t wait to see how workspaces evolve over time.<\/p>\n<ul>\n<li><a href=\"https:\/\/github.com\/mhartington\/vue-monorepo\">Sample Vue with npm workspaces repo on GitHub<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>This is part three of a new series on monorepos. By the end of the series, you&#8217;ll have the tools you need to adopt monorepo setups in your organization. Rounding out our series on monorepos, we take a look at an old friend, but a newcomer to the monorepo game, npm. Npm has long been [&hellip;]<\/p>\n","protected":false},"author":5,"featured_media":3679,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"publish_to_discourse":"1","publish_post_category":"29","wpdc_auto_publish_overridden":"","wpdc_topic_tags":"","wpdc_pin_topic":"","wpdc_pin_until":"","discourse_post_id":"505499","discourse_permalink":"https:\/\/forum.ionicframework.com\/t\/monorepos-with-ionic-vue-and-npm\/209532","wpdc_publishing_response":"","wpdc_publishing_error":"","_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[124],"tags":[197,206,210,147],"class_list":["post-3677","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-tutorials","tag-ionic-vue","tag-monorepos","tag-npm","tag-vue"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v23.0 (Yoast SEO v23.0) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Monorepos with Ionic, Vue, and npm - Ionic Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/ionic.io\/blog\/monorepos-with-ionic-vue-and-npm\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Monorepos with Ionic, Vue, and npm\" \/>\n<meta property=\"og:description\" content=\"This is part three of a new series on monorepos. By the end of the series, you&#8217;ll have the tools you need to adopt monorepo setups in your organization. Rounding out our series on monorepos, we take a look at an old friend, but a newcomer to the monorepo game, npm. Npm has long been [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/ionic.io\/blog\/monorepos-with-ionic-vue-and-npm\" \/>\n<meta property=\"og:site_name\" content=\"Ionic Blog\" \/>\n<meta property=\"article:published_time\" content=\"2021-05-14T16:27:07+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2021\/05\/npm-feature-image-1.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1600\" \/>\n\t<meta property=\"og:image:height\" content=\"880\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Mike Hartington\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@mhartington\" \/>\n<meta name=\"twitter:site\" content=\"@ionicframework\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Mike Hartington\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"6 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/ionic.io\/blog\/monorepos-with-ionic-vue-and-npm#article\",\"isPartOf\":{\"@id\":\"https:\/\/ionic.io\/blog\/monorepos-with-ionic-vue-and-npm\"},\"author\":{\"name\":\"Mike Hartington\",\"@id\":\"https:\/\/ionic.io\/blog\/#\/schema\/person\/c8c92b04d526adb925ea514c619a267b\"},\"headline\":\"Monorepos with Ionic, Vue, and npm\",\"datePublished\":\"2021-05-14T16:27:07+00:00\",\"dateModified\":\"2021-05-14T16:27:07+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/ionic.io\/blog\/monorepos-with-ionic-vue-and-npm\"},\"wordCount\":793,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/ionic.io\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/ionic.io\/blog\/monorepos-with-ionic-vue-and-npm#primaryimage\"},\"thumbnailUrl\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2021\/05\/npm-feature-image-1.png\",\"keywords\":[\"Ionic Vue\",\"Monorepos\",\"npm\",\"Vue\"],\"articleSection\":[\"Tutorials\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/ionic.io\/blog\/monorepos-with-ionic-vue-and-npm#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/ionic.io\/blog\/monorepos-with-ionic-vue-and-npm\",\"url\":\"https:\/\/ionic.io\/blog\/monorepos-with-ionic-vue-and-npm\",\"name\":\"Monorepos with Ionic, Vue, and npm - Ionic Blog\",\"isPartOf\":{\"@id\":\"https:\/\/ionic.io\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/ionic.io\/blog\/monorepos-with-ionic-vue-and-npm#primaryimage\"},\"image\":{\"@id\":\"https:\/\/ionic.io\/blog\/monorepos-with-ionic-vue-and-npm#primaryimage\"},\"thumbnailUrl\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2021\/05\/npm-feature-image-1.png\",\"datePublished\":\"2021-05-14T16:27:07+00:00\",\"dateModified\":\"2021-05-14T16:27:07+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/ionic.io\/blog\/monorepos-with-ionic-vue-and-npm#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/ionic.io\/blog\/monorepos-with-ionic-vue-and-npm\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/ionic.io\/blog\/monorepos-with-ionic-vue-and-npm#primaryimage\",\"url\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2021\/05\/npm-feature-image-1.png\",\"contentUrl\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2021\/05\/npm-feature-image-1.png\",\"width\":1600,\"height\":880},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/ionic.io\/blog\/monorepos-with-ionic-vue-and-npm#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/ionic.io\/blog\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Monorepos with Ionic, Vue, and npm\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/ionic.io\/blog\/#website\",\"url\":\"https:\/\/ionic.io\/blog\/\",\"name\":\"ionic.io\/blog\",\"description\":\"Build amazing native and progressive web apps with the web\",\"publisher\":{\"@id\":\"https:\/\/ionic.io\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/ionic.io\/blog\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/ionic.io\/blog\/#organization\",\"name\":\"Ionic\",\"url\":\"https:\/\/ionic.io\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/ionic.io\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/10\/white-on-color.png\",\"contentUrl\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/10\/white-on-color.png\",\"width\":1920,\"height\":854,\"caption\":\"Ionic\"},\"image\":{\"@id\":\"https:\/\/ionic.io\/blog\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/x.com\/ionicframework\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/ionic.io\/blog\/#\/schema\/person\/c8c92b04d526adb925ea514c619a267b\",\"name\":\"Mike Hartington\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/ionic.io\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2018\/08\/mike-headshot-2-smaller-150x150.png\",\"contentUrl\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2018\/08\/mike-headshot-2-smaller-150x150.png\",\"caption\":\"Mike Hartington\"},\"description\":\"Director of Developer Relations\",\"sameAs\":[\"https:\/\/twitter.com\/mhartington\",\"https:\/\/x.com\/mhartington\"],\"url\":\"https:\/\/ionic.io\/blog\/author\/mike\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Monorepos with Ionic, Vue, and npm - Ionic Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/ionic.io\/blog\/monorepos-with-ionic-vue-and-npm","og_locale":"en_US","og_type":"article","og_title":"Monorepos with Ionic, Vue, and npm","og_description":"This is part three of a new series on monorepos. By the end of the series, you&#8217;ll have the tools you need to adopt monorepo setups in your organization. Rounding out our series on monorepos, we take a look at an old friend, but a newcomer to the monorepo game, npm. Npm has long been [&hellip;]","og_url":"https:\/\/ionic.io\/blog\/monorepos-with-ionic-vue-and-npm","og_site_name":"Ionic Blog","article_published_time":"2021-05-14T16:27:07+00:00","og_image":[{"width":1600,"height":880,"url":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2021\/05\/npm-feature-image-1.png","type":"image\/png"}],"author":"Mike Hartington","twitter_card":"summary_large_image","twitter_creator":"@mhartington","twitter_site":"@ionicframework","twitter_misc":{"Written by":"Mike Hartington","Est. reading time":"6 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/ionic.io\/blog\/monorepos-with-ionic-vue-and-npm#article","isPartOf":{"@id":"https:\/\/ionic.io\/blog\/monorepos-with-ionic-vue-and-npm"},"author":{"name":"Mike Hartington","@id":"https:\/\/ionic.io\/blog\/#\/schema\/person\/c8c92b04d526adb925ea514c619a267b"},"headline":"Monorepos with Ionic, Vue, and npm","datePublished":"2021-05-14T16:27:07+00:00","dateModified":"2021-05-14T16:27:07+00:00","mainEntityOfPage":{"@id":"https:\/\/ionic.io\/blog\/monorepos-with-ionic-vue-and-npm"},"wordCount":793,"commentCount":0,"publisher":{"@id":"https:\/\/ionic.io\/blog\/#organization"},"image":{"@id":"https:\/\/ionic.io\/blog\/monorepos-with-ionic-vue-and-npm#primaryimage"},"thumbnailUrl":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2021\/05\/npm-feature-image-1.png","keywords":["Ionic Vue","Monorepos","npm","Vue"],"articleSection":["Tutorials"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/ionic.io\/blog\/monorepos-with-ionic-vue-and-npm#respond"]}]},{"@type":"WebPage","@id":"https:\/\/ionic.io\/blog\/monorepos-with-ionic-vue-and-npm","url":"https:\/\/ionic.io\/blog\/monorepos-with-ionic-vue-and-npm","name":"Monorepos with Ionic, Vue, and npm - Ionic Blog","isPartOf":{"@id":"https:\/\/ionic.io\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/ionic.io\/blog\/monorepos-with-ionic-vue-and-npm#primaryimage"},"image":{"@id":"https:\/\/ionic.io\/blog\/monorepos-with-ionic-vue-and-npm#primaryimage"},"thumbnailUrl":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2021\/05\/npm-feature-image-1.png","datePublished":"2021-05-14T16:27:07+00:00","dateModified":"2021-05-14T16:27:07+00:00","breadcrumb":{"@id":"https:\/\/ionic.io\/blog\/monorepos-with-ionic-vue-and-npm#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/ionic.io\/blog\/monorepos-with-ionic-vue-and-npm"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/ionic.io\/blog\/monorepos-with-ionic-vue-and-npm#primaryimage","url":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2021\/05\/npm-feature-image-1.png","contentUrl":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2021\/05\/npm-feature-image-1.png","width":1600,"height":880},{"@type":"BreadcrumbList","@id":"https:\/\/ionic.io\/blog\/monorepos-with-ionic-vue-and-npm#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/ionic.io\/blog"},{"@type":"ListItem","position":2,"name":"Monorepos with Ionic, Vue, and npm"}]},{"@type":"WebSite","@id":"https:\/\/ionic.io\/blog\/#website","url":"https:\/\/ionic.io\/blog\/","name":"ionic.io\/blog","description":"Build amazing native and progressive web apps with the web","publisher":{"@id":"https:\/\/ionic.io\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/ionic.io\/blog\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/ionic.io\/blog\/#organization","name":"Ionic","url":"https:\/\/ionic.io\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/ionic.io\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/10\/white-on-color.png","contentUrl":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/10\/white-on-color.png","width":1920,"height":854,"caption":"Ionic"},"image":{"@id":"https:\/\/ionic.io\/blog\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/x.com\/ionicframework"]},{"@type":"Person","@id":"https:\/\/ionic.io\/blog\/#\/schema\/person\/c8c92b04d526adb925ea514c619a267b","name":"Mike Hartington","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/ionic.io\/blog\/#\/schema\/person\/image\/","url":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2018\/08\/mike-headshot-2-smaller-150x150.png","contentUrl":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2018\/08\/mike-headshot-2-smaller-150x150.png","caption":"Mike Hartington"},"description":"Director of Developer Relations","sameAs":["https:\/\/twitter.com\/mhartington","https:\/\/x.com\/mhartington"],"url":"https:\/\/ionic.io\/blog\/author\/mike"}]}},"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2021\/05\/npm-feature-image-1.png","_links":{"self":[{"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/posts\/3677","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/users\/5"}],"replies":[{"embeddable":true,"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/comments?post=3677"}],"version-history":[{"count":0,"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/posts\/3677\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/media\/3679"}],"wp:attachment":[{"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/media?parent=3677"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/categories?post=3677"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/tags?post=3677"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}