kahirokunn
twitter: https://twitter.com/kahirokunn
qiita: https://qiita.com/kahirokunn
![](https://media.slid.es/uploads/891964/images/5504784/icon.jpg)
Vue.jsとReactが大好きで毎日書いてます.
最近の日課はVue 3 エコシステムからStable releaseがされてないか確認すること
話1つ目
Vueのエコシステムの現時点の状況
[@vue/cli](https://www.npmjs.com/package/@vue/cli) vue-cliでは既にvue2,vue3どちらでプロジェクトを作成するか選べる [vue-loader@16.0.0-rc.1](https://www.npmjs.com/package/vue-loader) [vuex@4.0.0-rc.1](https://www.npmjs.com/package/vuex) [vue-router@4.0.0-rc.3](https://www.npmjs.com/package/vue-router) [vee-validate@4.0.0-beta.19](https://www.npmjs.com/package/vee-validate) [vue-apollo-composable@4.0.0-alpha.12](https://www.npmjs.com/package/@vue/apollo-composable) [buefy](https://www.npmjs.com/package/buefy) buefyは無償のメンテナで構成されており、その為Vue3対応に対して積極的に進められておらず、Vue3対応プロジェクト自体も開始できていない. Issue: https://github.com/buefy/buefy/issues/2505 [vuetify](https://www.npmjs.com/package/vuetify) VuetifyのロードマップではVuetify 3.0でVue3対応する予定です. https://vuetifyjs.com/en/introduction/roadmap [nuxt](https://github.com/nuxt/nuxt.js/issues/5708#issuecomment-668555312) 現在進行中 [storybook](https://www.npmjs.com/package/storybook) StorybookのVue3対応は、Vueのエコシステムからrcが取れてから進みそうな気配があります. rcが取れれば立候補者が恐らく登場し、v6.2.0から使えるようになりそうな気がしています.
※2020年11月15日時点 Vue3対応待ちライブラリと時点でリリースされているバージョン番号 バージョン番号がないのは、Vue3対応がいつされるかわからないものです.
[@vue/cli](https://www.npmjs.com/package/@vue/cli) vue-cliでは既にvue2,vue3どちらでプロジェクトを作成するか選べる [vue-loader@16.0.0-rc.1](https://www.npmjs.com/package/vue-loader) [vuex@4.0.0-rc.1](https://www.npmjs.com/package/vuex) [vue-router@4.0.0-rc.3](https://www.npmjs.com/package/vue-router)
※2020年11月15日時点
時点でリリースされている公式のエコシステムをいくつかピックアップ
ついに公式のエコシステムはついにrcまで来てる!
[vue-apollo-composable@4.0.0-alpha.12](https://www.npmjs.com/package/@vue/apollo-composable) [buefy](https://www.npmjs.com/package/buefy) buefyは無償のメンテナで構成されており、その為Vue3対応に対して積極的に進められておらず、Vue3対応プロジェクト自体も開始できていない. Issue: https://github.com/buefy/buefy/issues/2505 [vuetify](https://www.npmjs.com/package/vuetify) VuetifyのロードマップではVuetify 3.0でVue3対応する予定です. https://vuetifyjs.com/en/introduction/roadmap [nuxt](https://github.com/nuxt/nuxt.js/issues/5708#issuecomment-668555312) 現在進行中 [storybook](https://www.npmjs.com/package/storybook) StorybookのVue3対応は、Vueのエコシステムからrcが取れてから進みそうな気配があります. rcが取れれば立候補者が恐らく登場し、v6.2.0から使えるようになりそうな気がしています.
※2020年11月15日時点 時点でリリースされているサードパーティのエコシステムをいくつかピックアップ
サードパーティのVue3対応はこれからな感じ
![](https://media.slid.es/uploads/891964/images/7947510/pasted-from-clipboard.png)
![](https://media.slid.es/uploads/891964/images/7947510/pasted-from-clipboard.png)
![](https://media.slid.es/uploads/891964/images/7947510/pasted-from-clipboard.png)
![](https://media.slid.es/uploads/891964/images/7947543/pasted-from-clipboard.png)
StorybookはVue3対応してくれる人募集している
その他エコシステムもそういう方を募集している
![](https://media.slid.es/uploads/891964/images/7947552/pasted-from-clipboard.png)
つまり
![](https://media.slid.es/uploads/891964/images/7947562/pasted-from-clipboard.png)
![](https://media.slid.es/uploads/891964/images/7947567/pasted-from-clipboard.png)
コントリビュートチャンス!
皆でVue3を盛り上げよう!
![](https://media.slid.es/uploads/891964/images/7947580/pasted-from-clipboard.png)
話2つ目
react-router-route-generatorを作った話
経緯
諸事情により最近Reactを書いているのだが、auto routingか同等の物がReactで欲しかった.
でないと、創作意欲が凝らされた最高の戦闘力を持つpage達が誕生してしまう.
機械的に管理できるレールを引きたかった.
Next.jsとかにはこの手の仕組が搭載されているが、単体でそれだけをしてくれるライブラリが見当たらなかった.
なので、作成した.
仕様
仕様は、Next.jsのpagesと同じものを与えると、その通りにルーティングします.
もしサポートされてない機能で欲しいものがあったらIssue立ててくれたら素早く対応すると思います.
また、useParams hooks等で利用すると便利な型も吐いてくれます.
![](https://media.slid.es/uploads/891964/images/7947670/pasted-from-clipboard.png)
- pages/post/[pid].tsx => /post/1, /post/abc
- pages/post/[...slug].tsx => /post/a, /post/a/b, /post/a/b/c
import React from 'react'; import { Route } from 'react-router'; import loadable from '@loadable/component'; export type UseParamsType = { ['/users/[userId]']: { ['userId']: string }; }; export const RouteConfig = { ['/users/:userId']: loadable(() => import('@/pages/users/[userId]/index.tsx')), ['/users']: loadable(() => import('@/pages/users/index.tsx')), ['/']: loadable(() => import('@/pages/index.tsx')), }; export default () => ( <> <Route path="/users/:userId" component={RouteConfig['/users/:userId']} exact /> <Route path="/users" component={RouteConfig['/users']} exact /> <Route path="/" component={RouteConfig['/']} exact /> </> );
$ npm install -D react-router-route-generator
$ npx generate-routes
簡単に使える
実装は簡単なルールベースで最小限のコードで済む様にした
大体Next.jsのルールを満たすように正規表現で実装している.
詳しく聞きたい場合は、個別に聞いてくれると幸いです!
import glob from 'glob'; import compareFunc from 'compare-func'; function assertsHasValue<T>( value: T, errorMessage: string, ): asserts value is Exclude<T, null | undefined | void> { if (value === null || value === undefined) { throw new Error(errorMessage); } } function globSync( patterns: string | string[], ignorePatterns: string[], ): string[] { if (typeof patterns === 'string') { patterns = [patterns]; } return patterns.reduce( (acc, pattern) => acc.concat(glob.sync(pattern, { nodir: true, ignore: ignorePatterns })), [] as string[], ); } type Slug = { name: string; isRest: boolean; }; type Slugs = Slug[]; type MetaData = { component: string; urlPath: string; path: string; slugs?: Slugs; isLastOptional: boolean; }; // 拡張子を取り除く // .replace(/^(.*)\.(js|jsx|ts|tsx)$/, '$1') function genRouteMetaData(componentPath: string, prefetch: boolean): MetaData { let urlPath = componentPath // 末尾の/index.{js,jsx,ts,tsx} を消す .replace(/^(.*)\/index\.(js|jsx|ts|tsx)$/, '$1') // 先頭の@/pagesを取り除く .replace(/^@\/pages(.*)$/, '$1'); const isLastOptional = /^(.*)\.(js|jsx|ts|tsx)$/.test(urlPath); if (isLastOptional) { urlPath = urlPath.replace(/^(.*)\.(js|jsx|ts|tsx)$/, '$1'); } return _calcRouteMetaData({ path: urlPath, isLastOptional, component: `() => import(${ prefetch ? '/* webpackPrefetch: true */' : '' } '${componentPath}')` // 拡張子を取り除く .replace(/^(.*)\.(js|jsx|ts|tsx)$/, '$1'), urlPath: urlPath === '' ? '/' : urlPath, }); } // hoge/fuga/[piyo]/[piyopiyo] => hoge/fuga/:piyo/:piyopiyo function _calcRouteMetaData(metaData: MetaData): MetaData { const result = /^(.*)\[(.*?)\](.*)$/.exec(metaData.urlPath); if (!result) { if (metaData.isLastOptional) { const items = metaData.urlPath.split('/'); items[items.length - 1] = `${items[items.length - 1]}?`; metaData = { ...metaData, urlPath: items.join('/'), }; } return metaData; } result.reverse(); let isRest = false; const slug = /^\.\.\.(.*)$/.exec(result[1]); if (slug) { isRest = true; result[1] = slug[1]; } return _calcRouteMetaData({ ...metaData, urlPath: isRest ? `${result[2]}:${result[1]}(.*)` : `${result[2]}:${result[1]}${result[0]}`, slugs: [ ...(metaData.slugs ?? []), { name: result[1], isRest, }, ], }); } function route2RouteConfig(route: MetaData, wrap: string) { return ` ['${route.urlPath}']: ${wrap.replace('$1', route.component)} `; } function route2RouteComponent(route: MetaData) { return ` <Route path='${route.urlPath}' component={RouteConfig["${route.urlPath}"]} exact /> `; } type GenCodeInput = Partial<{ sourceHead: string; wrap: string; targetDir: string; ignorePatterns: string[]; prefetch: boolean; }>; export function generate(params: GenCodeInput) { const { sourceHead = "import React from 'react'; import { Route } from 'react-router'; import loadable from '@loadable/component';", wrap = 'loadable($1)', targetDir = 'src/pages', ignorePatterns = [], prefetch = false, } = params; const routes = globSync(`${targetDir}/**/*`, ignorePatterns) .map((filePath) => { const result = /^src\/(.*)$/.exec(filePath); assertsHasValue(result, "There can't be an error here."); return `@/${result[1]}`; }) .map((componentPath) => genRouteMetaData(componentPath, prefetch)) .sort(compareFunc('urlPath')) .reverse(); const typeCode = `export type UseParamsType = { ${routes .filter((route) => route.slugs) .map( (route) => `['${route.path}']: { ${(route.slugs as Slugs) .map((slug) => `['${slug.name}']: string`) .join(';')} }`, ) .join(';')} }`; const routesCode = ` ${sourceHead} ${typeCode} export const RouteConfig = { ${routes.map((route) => route2RouteConfig(route, wrap))} } export default () => ( <> ${routes.map((route) => route2RouteComponent(route)).join('')} </> ) `; return { routesCode, }; }
ご静聴ありがとうございました
kahirokunn twitter: https://twitter.com/kahirokunn qiita: https://qiita.com/kahirokunn Vue.jsとReactが大好きで毎日書いてます. 最近の日課は Vue 3 エコシステムから Stable releaseが されてないか確認すること
icare lt
By kahirokunn
icare lt
- 1,521