【JS】Next.jsをAMPに移行する際につまづいた部分一覧
こんにちは!AMPはあんまり好きじゃないMizutani(@sirycity)です。Chromeで見ると翻訳ができないんだよねー
それは別として、このブログは4月6日よりAMPに移行しました。Next.jsはAMPモードがあるからこの1行を付けるだけで簡単に移行…
export const config = { amp: true }
とはならず、あっちこっちでつまづいたのでつまづいた部分を書いておきます。反面教師にしてね。
imgがamp-imgになる
これはまあAMP全般で起こることですね。でもReact+TypeScriptの場合いきなり<amp-img>って書いたらこんなタグ知らんわって怒られるので型情報を追加しなきゃいかん。
これはルートにnext-env.d.ts
って名前のファイルを作ってそこに以下を追記すればok。ルートはpackage.json
とかある階層ね。
// Any element you create will be accepted
declare namespace JSX {
interface IntrinsicElements {
[elemName: string]: any
}
}
// The elements you list here will be accepted, attributes don't matter
declare namespace JSX {
interface IntrinsicElements {
'amp-img': any
}
}
// The elements you list here will be accepted, and only with the attributes that you include here
declare namespace JSX {
interface AmpImg {
alt?: string
src?: string
width?: string
height?: string
layout?: string
}
interface IntrinsicElements {
'amp-img': AmpImg
}
}
これでimgをamp-imgに変えれる。ちなみにmarkdownから変換される<img>は<amp-img>に変えるのが大変だけど、そんな時はmarkdownの中に直接<amp-img>書けばok。ちょっと気持ち悪いけどね。
CSSの外部読み込みができない
※2022/4/19追記: もっと簡単な設定方法があったので変更
cssって普通はこんな感じに読み込むけど…
import '../styles/styles.css'
AMPではできない。AMPはCSSファイル外部から読み込めないから。例外はあるけど。
でもCSSを直接記入するのはOK。こんな感じに。
<style>{`.foo{width: auto}`}</style>
なのでwebpackを使ってCSSファイルを文字列として読み込むみたいな感じになる。めんどいね。僕もwebpack嫌い。でもしょうがない。
まずはraw-loaderとpostcss-loaderってライブラリを追加。これがcssを文字列にするやつ。
npm i raw-loader postcss-loader
次にwebpackの設定をいじるんだけど、nextjsだとnext.config.js
ってファイルがあるからそこにこれを追記。
module.exports = {
webpack: config => {
config.module.rules.push({
test: /\.css$/,
use: ['raw-loader', 'postcss-loader'],
})
return config
},
}
cssって付くファイルにloaderを適用するなーって感じの宣言。
そしたら最後に普通にimportして<style>の中に流し込んで終わり。
import foo from '../styles/styles.css'
;<style
dangerouslySetInnerHTML={{
__html: foo,
}}
/>
cssのサイズに上限がある
↑みたいにやって終われば良いんだけど、CSSフレームワークを使っているとCSSがめっちゃ大量になってAMPのCSS上限に引っかかる。CSSをwebpackで文字列に変換→文字列を読み込みってやるとサイズ制限に引っかかるんですね。 そこでPostCSSを使ってCSSをpostcssで小さいCSSに変換→小さいCSSをwebpackで文字列に変換→文字列を読み込みみたいにする。 いくつか方法があるけどなるべく簡単な例で。まずはこの辺をインストールして…
npm i -D postcss postcss-cli @fullhuman/postcss-purgecss
次にルートに.postcssrc.js
ってのを作って、こんな感じに。
module.exports = {
plugins: [
require('@fullhuman/postcss-purgecss')({
content: ['./{pages,components}/**/*.{js,jsx,ts,tsx}'],
defaultExtractor: content => content.match(/[\w-/:]+(?<!:)/g) || [],
}),
],
}
ほんとはもっといろんなプラグイン使うと良いけど、purgecssさえあればとりあえずサイズ制限はクリアできるはず。
google analyticsが動かない
GAはamp-analyticsっていうAMP専用のがあるのでそれに移行。
npmとか使う必要はないよ、nextjsの場合は_document.tsx
に2つ書くだけ。
まずはHead
の直前にこれ。
<script
async
custom-element="amp-analytics"
src="https://cdn.ampproject.org/v0/amp-analytics-0.1.js"
/>
次にbody
の直後にこれ。
<amp-analytics type="gtag" data-credentials="include">
<script
type="application/json"
dangerouslySetInnerHTML={{
__html: `
{
"vars": {
"gtag_id": "${analyticsのID}",
"config": {
"${analyticsのID}" : { "groups": "default" }
}
}
}`,
}}
/>
</amp-analytics>
analyticsのIDはそのままでOK!
google adsenseが動かない
普通のアドセンスだとreact-adsenseってライブラリがあるんだけど、AMPは別。AMPも2箇所書くよ。
1つ目は_document.tsx
のhead
の直前。analyticsと一緒。
<script
async
custom-element="amp-ad"
src="https://cdn.ampproject.org/v0/amp-ad-0.1.js"
/>
2つ目はadsenseのコンポーネントを作る。こんな感じ。
export const Ad = () => (
<amp-ad
width="100vw"
height="320"
type="adsense"
data-ad-client={ca-pub-462391857264みたいなやつ}
data-ad-slot={725483976978236みたいなやつ}
data-auto-format="rspv"
data-full-width=""
>
<div overflow=""></div>
</amp-ad>
)
こちらも環境変数は変更なし。でもGoogleAdsenseはそもそもディスプレイ広告しかAMPに対応していないので注意。
さいごに
AMP対応は意外とめんどい。まだこのブログも移行したばかりなので気づいたら追記します!以上。