VSCodeCon JP の内幕
~ カンファレンス LP について~
2021/11/01
VSCodeCon JP プレイベント
jiyuujin
- 複雑なUIを作るのが好きです
- React/Next/Vue/Nuxt/Scala/Swift
- スタッフとして色々と参画中
- FlutterKaigi 2021
- JAWS DAYS 2021 個人スポンサー
- Flutter Japan User Group (Osaka)
- PWA night
- v-kansai / kansai.ts
- プロフィールサイト
- https://yuma-kitamura.nekohack.me
- 技術ブログ
- https://webneko.dev
VSCodeCon JP
- https://vscodejp.github.io/conf2021/ja/
- https://vscodejp.github.io/conf2021/en/
今年の VSCodeCon 実は
- 今年で 6 年目を迎える VS Code Conference JP 2021 で初めてカンファレンスウェブサイトを製作した
- スタッフ投票の結果 Happy Extensions をコンセプトとして採用している
VSCode のブランドカラー
- VSCodeCon ウェブサイトに VSCode のブランドカラー 3 色全てを織り交ぜた
- .vscode/settings.json でテーマカラーも設定した
{
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
},
"eslint.lintTask.enable": true,
"peacock.color": "#007acc",
"workbench.colorCustomizations": {
"activityBar.activeBackground": "#007acc",
"activityBar.activeBorder": "#ee90bb",
"activityBar.background": "#007acc",
"activityBar.foreground": "#e7e7e7",
"activityBar.inactiveForeground": "#e7e7e799",
"activityBarBadge.background": "#ee90bb",
"activityBarBadge.foreground": "#15202b",
"editorGroup.border": "#007acc",
"panel.border": "#007acc",
"sash.hoverBorder": "#007acc",
"sideBar.border": "#0065a9",
"statusBar.background": "#0098ff",
"statusBar.foreground": "#e7e7e7",
"statusBarItem.hoverBackground": "#007acc",
"statusBarItem.remoteBackground": "#0065a9",
"statusBarItem.remoteForeground": "#e7e7e7",
"titleBar.activeBackground": "#0065a9",
"titleBar.activeForeground": "#e7e7e7",
"titleBar.inactiveBackground": "#1857a499",
"titleBar.inactiveForeground": "#e7e7e799"
}
}
見栄えが変わる
技術スタック
Deploy to
Github Pages
ざっくりこの 3 点
- Github Pages へデプロイする
- Next.js の静的サイト化を行う
- React フレームワークのひとつ Next.js の採用
- i18next を使って国際化 (EN/JA) に対応する
- Context とその Provider を使って Light/Dark 双方に対応する
Github Pages へデプロイ
- vscodejp.github.io というドメインで公開する方針の下 Github Pages へデプロイすることになった
- next build と next export を合わせて進めることで、静的 HTML が生成される
- Github Pages 固有の事象に対処する
- _ から始まるファイルが 404 となってしまう問題
jobs:
build-deploy:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [12.x]
steps:
- uses: actions/checkout@master
- name: Use Node.js
uses: actions/setup-node@master
with:
node-version: '12.x'
- name: Transpile
run: |
npm install
npm run build
env:
CI: true
URL_PREFIX: conf2021
GITHUB_PAGES: true
- name: Export
run: |
npm run export
touch out/.nojekyll
- name: Deploy
uses: peaceiris/actions-gh-pages@v2.8.0
env:
ACTIONS_DEPLOY_KEY: ${{ secrets.ACTIONS_DEPLOY_KEY }}
PUBLISH_BRANCH: gh-pages
PUBLISH_DIR: ./out
国際化対応に i18next を使う
- 唐突ながらハマりポイントは next-18next が静的サイト用に使えないこと
- Github issue が立てられていました
- useRouter を使うことでルートパスに言語ごとのパスへリダイレクトするよう設定する
- リダイレクトされた先でタイムテーブルなど具体的なコンテンツを配置する
Dynamic Routes を利用
- 言語別にルーティングを準備する
- ルーティングパスとして pages/[lang].tsx を準備する
- getStaticPaths / getStatisProps を使うことで事前に想定している言語を paths / props として返す
- 今回は英語と日本語を返す
export async function getStaticPaths() {
return {
paths: languages.map((lang) => {
return { params: { lang: lang } }
}),
fallback: false,
}
}
export async function getStaticProps({ params }) {
return {
props: {
language: languages.includes(params.lang) ? params.lang : defaultLanguage,
},
}
}
強制リダイレクトさせる
- ルートで各言語に応じたパスにアクセスさせる
- pages/index.tsx から強制リダイレクトさせる
- next/router の useRouter を使うことでユーザが入力したパスを判定する
- en/ja が入力された際各言語に応じたパスを返す
import React from 'react'
import { useRouter } from 'next/router'
import i18next from 'i18next'
export default function Home() {
const router = useRouter()
React.useEffect(() => {
const { pathname } = router
if (pathname == '/') {
router.push('/' + i18next.language.substring(0, 2))
}
})
return null
}
テーマを Context に保存
- Context は共通に使えるデータストア
- 一般的に言われているのは props のバケツリレーを避けるため
- 今回のテーマ保存はとある特定のコンポーネントに限定しないので、可能な限り Context という形式で管理した方が良さそう、という判断から
- テーマを Union 型で定義する
- colorMode: ColorMode = 'light' | 'dark'
- 保存したテーマを localStorage に保存する
Provider を登録する
- Context とその Provider を使ってテーマを保存する
- 事前に Light/Dark 双方で使う用の CSS variables を読み込む
- --initial-color-mode という名前の下で今のテーマを保存する
- クライアントでページがロードされた時に読み込む
- pages/_app.tsx で Provider を読み込む
type ColorTheme = {
colorMode: 'light' | 'dark'
changeColorMode: (cm: 'light' | 'dark') => void
}
export const ColorThemeContext = createContext<ColorTheme>(null)
export const ColorThemeProvider: FC = ({ children }) => {
const [colorMode, setColorMode] = useState(undefined)
useEffect(() => {
const root = window.document.documentElement
const initialColorValue = root.style.getPropertyValue('--initial-color-mode')
setColorMode(initialColorValue)
}, [])
const changeColorMode = (mode: string) => {
setColorMode(mode)
window.localStorage.setItem('color-mode', mode)
const root = window.document.documentElement
root.style.setProperty('--initial-color-mode', mode)
root.style.setProperty(
'--color-text',
mode === 'light' ? themeColors.light.textColor : themeColors.dark.textColor,
)
root.style.setProperty(
'--color-background',
mode === 'light' ? themeColors.light.backgroundColor : themeColors.dark.backgroundColor,
)
}
return (
<ColorThemeContext.Provider value={{ colorMode, changeColorMode }}>
{children}
</ColorThemeContext.Provider>
)
}
コントリビュート歓迎
https://github.com/vscodejp/conf2021
最後にこれだけは!
- VSCodeCon JP 今年のテーマは Happy Extensions
- VSCode で自分仕様にカスタマイズできる
- テーマカラーを設定できる
- Next.js SG 化
- next build と next export を合わせてビルドする
- Dark/Light 双方へ対応するには Context
- 国際化対応は注意が必要です
Thank you..🙇♀️
VSCode Conference ウェブサイト
By jiyuujin
VSCode Conference ウェブサイト
DevRel/Online #3 では Flutter Osaka を中心に
- 440