JavaScriptに関するお知らせ

SINCE2019
>
【JS】Next.jsをAMPに移行する際につまづいた部分一覧

【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-loaderpostcss-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.tsxheadの直前。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対応は意外とめんどい。まだこのブログも移行したばかりなので気づいたら追記します!以上。



PREV
2021-04-06
フロントエンドエンジニアから見たM1Macに変えて良かった事とそうでもない事

NEXT
2021-04-11
【JS】Next.jsのトレイリングスラッシュの設定と404ページが機能しない時の対策