Nuxt.js: sharing components

simple way to share components between multiple projects

Abstract

  • single repositoryで複数のprojectを管理する
  • ビルド時にnuxt.config.jsを上書きし, pagesをproject毎に分離

Motivation

  • adminuserで共通のコンポーネントがある
  • /user, /admin のようにルーティングで分ける方法もあるが, そもそも/admin を外に出したくない(同じ環境で動作させたくない)

1. setup subdir

create-nuxt-appで生成したテンプレートを元に, admin/ディレクトリ配下にサブプロジェクトを作成する.

$ mkdir -p admin/{pages,layouts}
$ touch admin/app.config.js
$ls
.gitignore
.nuxt/
admin/    <-- new
  layouts/
  pages/
  app.config.js
assets/
components/
...
layouts/  <-- default
pages/    <-- default

2. configure app.config.js

srcDiradminとすることで, Nuxtがみるプロジェクトがadmin/配下になる. これでNuxtが生成するroutingもadmin/pagesによるものになる. そのため, Storeをadmin側でも持ちたい場合はadmin/store/を作成する.

また, admin/pages/xxx.vue でもimport XXX from '@/components/...のように@を用いる為にbuildディレクティブで@ aliasを上書きする.
(この設定がない場合, @/../components/...のように root directoryまで1階層のぼる必要がある)

const path = require('path')
const merge = require('deepmerge')
const nuxt = require('../nuxt.config.js')

const extend = {
  srcDir: __dirname,
  buildDir: '.nuxt/admin',

  build: {
    extend(config) {
      config.resolve.alias['@'] = path.resolve(__dirname, '..')
    }
  }
}

export default merge(nuxt, extend)

3. configure package.json

nuxt--config-file オプションを用いてnuxt.config.jsを指定する.
これでyarn devとすればデフォルトのpagesが用いられるし, yarn dev:adminとすればadmin/pagesが用いられる.

{
  "scripts": {
    "dev": "nuxt",
    "build": "nuxt build",
    "start": "nuxt start",
    "dev:admin": "nuxt --config-file admin/app.config.js",
    "build:admin": "nuxt build --config-file admin/app.config.js",
    "start:admin": "nuxt start --config-file admin/app.config.js",
  },
  ...
}

Appendix: Generated Routing(.nuxt/admin/router.js)

yarn build:adminで生成されたroutesclient側のpagesが含まれていないことが確認できる.

import Vue from 'vue'
import Router from 'vue-router'
import { interopDefault } from './utils'
import scrollBehavior from './router.scrollBehavior.js'

const _0510df08 = () => interopDefault(import('../../admin/pages/index.vue' /* webpackChunkName: "pages/index" */))

Vue.use(Router)

export const routerOptions = {
  mode: 'history',
  base: decodeURI('/'),
  linkActiveClass: 'nuxt-link-active',
  linkExactActiveClass: 'nuxt-link-exact-active',
  scrollBehavior,

  routes: [{
      path: "/",
      component: _0510df08,
      name: "index"
    }],

  fallback: false
}

export function createRouter() {
  return new Router(routerOptions)
}

repository

koka831/nuxt-multiple-sample

Commits

2021-01-30 22:18:1735b550aecopy md
commit 35b550ae83af4efaeadf33471c8ca8a32c1079c8
Author: koka &>
Date:   Sat Jan 30 22:18:17 2021 +0900

  copy md

diff --git a/_posts/2019-10-06-nuxt-sharing-component.md b/_posts/2019-10-06-nuxt-sharing-component.md
new file mode 100644
index 0000000..6daf63f
--- /dev/null
+++ b/_posts/2019-10-06-nuxt-sharing-component.md
@@ -0,0 +1,124 @@
+---
+title: 'Nuxt.js: sharing components'
+date: 2019-10-06
+categories:
+- memo
+tags:
+- Vue
+description: simple way to share components between multiple projects
+---
+
+## Abstract
+- single repositoryで複数のprojectを管理する
+- ビルド時に`nuxt.config.js`を上書きし, `pages`をproject毎に分離
+
+## Motivation
+- `admin`と`user`で共通のコンポーネントがある
+- `/user`, `/admin` のようにルーティングで分ける方法もあるが, そもそも`/admin` を外に出したくない(同じ環境で動作させたくない)
+
+### 1. setup subdir
+[create-nuxt-app](https://github.com/nuxt/create-nuxt-app)で生成したテンプレートを元に, `admin/`ディレクトリ配下にサブプロジェクトを作成する.
+
+\```sh
+$ mkdir -p admin/{pages,layouts}
+$ touch admin/app.config.js
+$ls
+.gitignore
+.nuxt/
+admin/    <-- new
+  layouts/
+  pages/
+  app.config.js
+assets/
+components/
+...
+layouts/  <-- default
+pages/    <-- default
+
+\```
+
+
+### 2. configure app.config.js
+`srcDir`を`admin`とすることで, Nuxtがみるプロジェクトが`admin/`配下になる.
+これでNuxtが生成するroutingも`admin/pages`によるものになる.
+そのため, Storeをadmin側でも持ちたい場合は`admin/store/`を作成する.
+
+
+また, `admin/pages/xxx.vue` でも`import XXX from '@/components/...`のように`@`を用いる為に`build`ディレクティブで`@ alias`を上書きする.  
+(この設定がない場合, `@/../components/...`のように root directoryまで1階層のぼる必要がある)
+
+\```js
+const path = require('path')
+const merge = require('deepmerge')
+const nuxt = require('../nuxt.config.js')
+
+const extend = {
+  srcDir: __dirname,
+  buildDir: '.nuxt/admin',
+
+  build: {
+    extend(config) {
+      config.resolve.alias['@'] = path.resolve(__dirname, '..')
+    }
+  }
+}
+
+export default merge(nuxt, extend)
+\```
+
+### 3. configure package.json
+`nuxt`の`--config-file` オプションを用いて`nuxt.config.js`を指定する.  
+これで`yarn dev`とすればデフォルトの`pages`が用いられるし, `yarn dev:admin`とすれば`admin/pages`が用いられる.
+
+\```js
+{
+  "scripts": {
+    "dev": "nuxt",
+    "build": "nuxt build",
+    "start": "nuxt start",
+    "dev:admin": "nuxt --config-file admin/app.config.js",
+    "build:admin": "nuxt build --config-file admin/app.config.js",
+    "start:admin": "nuxt start --config-file admin/app.config.js",
+  },
+  ...
+}
+\```
+
+
+### Appendix: Generated Routing(.nuxt/admin/router.js)
+`yarn build:admin`で生成された`routes` に `client`側の`pages`が含まれていないことが確認できる.
+
+
+\```js
+import Vue from 'vue'
+import Router from 'vue-router'
+import { interopDefault } from './utils'
+import scrollBehavior from './router.scrollBehavior.js'
+
+const _0510df08 = () => interopDefault(import('../../admin/pages/index.vue' /* webpackChunkName: "pages/index" */))
+
+Vue.use(Router)
+
+export const routerOptions = {
+  mode: 'history',
+  base: decodeURI('/'),
+  linkActiveClass: 'nuxt-link-active',
+  linkExactActiveClass: 'nuxt-link-exact-active',
+  scrollBehavior,
+
+  routes: [{
+      path: "/",
+      component: _0510df08,
+      name: "index"
+    }],
+
+  fallback: false
+}
+
+export function createRouter() {
+  return new Router(routerOptions)
+}
+\```
+
+### repository
+[koka831/nuxt-multiple-sample](https://github.com/koka831/nuxt-multiple-sample)