Closed14
Eleventy + Web Components のサイトを Next.js でリプレイスするメモ
準備
プロジェクト作成
npx create-next-app プロジェクト名
GitHub
nex create-next-app
が Git の設定までしくれるので push しておくだけ
git remote add origin リポジトリURL
git push -u origin main
TypeScript
npm install --save-dev typescript @types/react @types/node
touch tsconfig.json
npm run dev
インストール後に一度開発サーバーを立ち上げることで、tsconfig.json
の中身が自動的に記述され、next-env.d.ts
が生成されます
ESLint
npm install -D eslint
前に導入したときから選択肢が変わっていたが、雰囲気で答えていきました。
npx eslint --init
✔ How would you like to use ESLint? · style
✔ What type of modules does your project use? · esm
✔ Which framework does your project use? · react
✔ Does your project use TypeScript? · No / Yes
✔ Where does your code run? · browser
✔ How would you like to define a style for your project? · guide
✔ Which style guide do you want to follow? · airbnb
✔ What format do you want your config file to be in? · JavaScript
✔ Would you like to install them now with npm? · No / Yes
導入後 package.json
に lint
系を追加し、npm run lint:fix
でエラーを一気に消しました
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "eslint . --ext .ts,.tsx",
"lint:fix": "eslint . --ext .ts,.tsx --fix"
},
npm run lint:fix でも消えないエラーは一旦無視させています
rules: {
'react/react-in-jsx-scope': 'off',
'react/jsx-filename-extension': 'off',
'react/jsx-props-no-spreading': 'off',
},
Vercel にリリース
Vercel で Repository を選択肢、ビルドのオプションなどは何も変更せずポチポチしてリリース
特に困ることもなくできた
TypeScript
ReturnType<typeof 関数名>
import styles from './button.module.css';
type Props = {
children: React.ReactNode;
onClick: () => void;
};
export default function Button(props: Props) {
const { children, onClick } = props;
return (
<button type="button" onClick={onClick} className={styles.button}>{children}</button>
);
}
2 画面を書き直した感想
- コアなロジック的なものは TypeScipt で書いてあったのでコピペでいけそう
- データを画面に描画するところが React, Next.js, TypeScript で書き心地が良い
- web components では素の DOM API を叩いてた
PWA
インストール
npm i next-pwa
next.config.js
をラップする
const withPWA = require('next-pwa');
module.exports = withPWA({
images: {
domains: [
'pbs.twimg.com',
],
},
i18n: {
locales: ['ja', 'en'],
defaultLocale: 'ja',
},
});
manifest.json
を public
配下に設置
{
"name": "Enjoy SFV More",
"short_name": "Enjoy SFV More",
"icons": [
{
"src": "/src/img/icon/logo-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/src/img/icon/maskable_icon.png",
"sizes": "192x192",
"type": "image/png",
"purpose": "any maskable"
},
{
"src": "/src/img/icon/logo-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"start_url": "/",
"display": "standalone",
"background_color": "#3E4EB8",
"theme_color": "#2F3BA2"
}
_document.tsx
の Head
に manifest.json
の読み込みや他の設定を追加
<link rel="manifest" href="/manifest.json" />
<meta name="theme-color" content="#2F3BA2" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="white" />
<meta name="apple-mobile-web-app-title" content="Enjoy SFV More" />
<link rel="apple-touch-icon" sizes="120x120" href="/src/img/icon/logo-512x512.png" />
<link rel="apple-touch-icon" sizes="180x180" href="/src/img/icon/logo-512x512.png" />
いろいろ足したら next build
を実行する
が、今作っているサイトが next build
に 30分かかる・・・
GA が AMP でエラーになる(カスタムスクリプトが存在すると言われる
dangerouslySetInnerHTML
で仕込んでいるところがエラーになる
<script
dangerouslySetInnerHTML={{
__html: `
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '${GA_TRACKING_ID}', {
page_path: window.location.pathname,
});
`,
}}
/>
とりあえず分けて実行してみた(なんとか動いていそう)
function MyApp({ Component, pageProps }) {
const router = useRouter();
useEffect(() => {
const handleRouteChange = (url) => {
// @ts-ignore
gtag('js', new Date());
// @ts-ignore
gtag('config', GA_TRACKING_ID, {
page_path: window.location.pathname,
});
pageview(url);
};
router.events.on('routeChangeComplete', handleRouteChange);
return () => {
router.events.off('routeChangeComplete', handleRouteChange);
};
}, [router.events]);
return <Component {...pageProps} />;
}
export const GA_TRACKING_ID = process.env.NEXT_PUBLIC_GA_TRACKING_ID;
// eslint-disable-next-line prefer-rest-params
export function gtag() { window.dataLayer.push(arguments); }
export const pageview = (url) => {
if (!GA_TRACKING_ID) {
return;
}
// @ts-ignore
gtag('config', GA_TRACKING_ID, {
page_path: url,
});
};
export const event = ({
action, category, label, value,
}) => {
if (!GA_TRACKING_ID) {
return;
}
// @ts-ignore
gtag('event', action, {
event_category: category,
event_label: label,
value,
});
};
このスクラップは2021/05/04にクローズされました