チュートリアル html javascript Node.js Webデザイン スマートフォン

シンプルなAMPページのコーディング環境をgulpを使って用意してみる。

AMPページを作る時はwordpressのプラグインやシステム側で生成させたりすることもあるかもしれませんが、 試しに静的数ページ運用してみたいなときに、わざわざwordpressを設置したり、 そういった変換システムを作るというのは、試したいだけなのに、ややコストが高いです。 (すでにあるなら知りたい。。)

とはいえ、静的に作るとすれば、cssもhtml内に書かないといけないし、 更新するときにソースが長くなって見づらいし、通常のcssと共有しづらいし、 保守性がさがってしまいますよね。

なので、静的サイトのhtmlとcssのコーディングするかのようなコーディング方法で できないかなと思い、gulpのタスクを組み合わせて作ってみました。

今回はLP1ページを作成するというのを想定して環境を構築してみたいと思います。 タスクランナーのgulpを使って構築していきます。 そのため前提として、node.js,npm,gulpを触ったことがあるという前提で 進行させていただきます。

試した環境

OS:windows
NodeJsバージョン: 8.x.x以上
npm : 5.30

package.jsonは後述します。

ディレクトリ構成

/index.html -> 通常のhtml
├ index.amp_base.html -> cssが挿入される前のamp html
├ index.amp.html      ->  cssが挿入された後のamp html
├ css
│ ├ style.scss
│ ├ style.css
├─images/~

処理の流れのイメージ

[scssのコンパイル]
 ↓
[コンパイルされたcssのパスを変更して]
 ↓
[index.amp.htmlにstyle要素を作成して挿入する]

パスを変更しないと、cssからの相対パスで探してしまうため、 urlを使って指定したものが見つからなくなるので、index.htmlからの相対パスに変更します。 /絶対パスであれば、問題ないと思いますので、処理は飛ばしても構いません。

packge.json

{
  "private": true,
  "scripts": {
    "gulp": "gulp"
  },
  "devDependencies": {
    "gulp": "^3.9.1",
    "gulp-amphtml-validator": "^1.0.1",
    "gulp-changed": "^2.0.0",
    "gulp-clean-css": "^3.6.0",
    "gulp-inject": "^4.2.0",
    "gulp-plumber": "^1.1.0",
    "gulp-rename": "^1.2.2",
    "gulp-sass": "^3.1.0",
    "gulp-sourcemaps": "^2.4.1",
    "run-sequence": "^1.2.2"
  },
}

ベースとなる index.amp_base.htmlを用意します

<!doctype html>
<html amp lang="ja">
<head>
	<meta charset="utf-8" />
	<title>AMP minial template | Actzero</title>
	<meta name="description" content="AMP minial template for Actzero"/>
	<meta name="keywords" content="AMP minial template,Actzero"/>
	<meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,user-scalable=no" />
	<link rel="canonical" href="ページURL(初回からAMPならAMPのページ)" />
	<link rel="amphtml" href="AMPのページURL(通常版がある時に利用する)" />

	<script type="application/ld+json">
	~~ 省略 ~~
	</script>

	<style amp-boilerplate>body{-webkit-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-moz-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-ms-animation:-amp-start 8s steps(1,end) 0s 1 normal both;animation:-amp-start 8s steps(1,end) 0s 1 normal both}@-webkit-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-moz-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-ms-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-o-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}</style><noscript><style amp-boilerplate>body{-webkit-animation:none;-moz-animation:none;-ms-animation:none;animation:none}</style></noscript>

	<!-- inject:inline-style:start -->
	<!-- この中にcssが入ります。 -->
	<!-- inject:inline-style:end -->

	<script async src="https://cdn.ampproject.org/v0.js"></script>
</head>
<body>
<h1>ページコンテンツ</h1>
</body>
</html>
@charset "UTF-8";

/* css/style.scss */
body  {
    background: url('../background.jpg');
}

gulpfile.jsでタスクを作成していきます。

scssのコンパイルタスク

まずはscssのコンパイルタスクを作成します。 最後にminifyしてもいいのですが、今回はここの段階でしておきます。 圧縮する処理も追加しておきます。

// 諸々のライブラリ読み込み
const gulp        = require('gulp');
const inject      = require('gulp-inject');
const plumber     = require('gulp-plumber');
const sass        = require('gulp-sass');
const sourcemaps  = require('gulp-sourcemaps');
const cleanCss    = require('gulp-clean-css');
const runSequence = require('run-sequence');
const rename      = require('gulp-rename');

const paths =  {
	src : '.',
	dist: '.'
};

gulp.task('styles', function () {
	return gulp.src([`${paths.src}/css/**/*.scss`])
		.pipe(plumber({ // エラー抑制
			errorHandler : function(err) {
				console.log(err);
			}
        }))
        .pipe(sourcemaps.init())
		.pipe(sass().on('error', sass.logError))
		.pipe(cleanCss({compatibility: 'ie8'})) // cssを圧縮
		.pipe(sourcemaps.write('./'))
		.pipe(gulp.dest(`${paths.src}/css`));
});

cssを加工 -> htmlへ挿入するタスク

gulp-injectというライブラリを利用すると、 html内に色々と挿入することができるので今回はそれを利用します。

  • 指定したcssファイルの中身を取得後
  • style属性内用に加工
  • 事前に用意していたhtmlの指定コメント内に加工したcssを挿入

補足

今回は1ページだけを想定しているため、 相対パスの調整は置換で行ってしまっていますが、 本来は適切なパスを取得できるようなスクリプトを書いた方がいいかと思います。

gulp.task('inject-styles', function() {
    return gulp.src(`${paths.dist}/index.amp_base.html`)
        // gulp-injectを使いamp.html内のコメントに生成されたcssの内容を挿入する
		.pipe(inject(gulp.src([`${paths.dist}/css/style.css`]), {
			starttag : '<!-- inject:inline-style:start -->',
			endtag   : '<!-- inject:inline-style:end -->',
			relative : true,
			removeTags: true,
			transform: function(filePath, file) {
                const styleTagStart = '<style amp-custom>';
                const styleTagEnd  = '</style>';

                // スタイルの中身をstyle属性内用に加工していきます。
                let styles = file.contents.toString('utf8');
                // パスを相対パスを変更する。
                styles = styles.replace('url(../', 'url(');
                // sassコンパイル時に生成される行を削除する
				styles = styles.replace(/\/\*\#\ssourceMappingURL\=.*\.map\s\*\//i, '');
                styles = styles.replace(/\@charset \"utf-8\"\;/i, '').trim();
                
                return styleTagStart 
                        + styles 
                        + styleTagEnd;
			}
		}))
		.pipe(rename('index.amp.html'))
		.pipe(gulp.dest(`${paths.dist}`))
});

最後に処理の順番を指定します。

互いのタスクはできましたが、watchなどで監視した際に inject -> style(scss) の順になってしまっては、正しく生成されませんので、
style(scss) -> injectになるようにします。 順番の指定などはrun-sequenceというライブラリで調整することができます。

 gulp.task('ampdev', function(callback) {
	runSequence(['styles'], 'inject-styles', callback);
});

最後にwatchタスク作成

これで一連のタスク作成が完了です。

gulp.task('default',['ampdev'], function() {
	gulp.watch([`${paths.src}/**/*.+(html|scss|js|jpg|jpeg|JPG|gif|GIF|png|PNG)`,`!index.amp.html`, '!./node_modules/**/*'], ['ampdev']);
});

実行

実行するときは

npm run gulp

で実行します。
グローバルgulpが入っている人は

gulp

でも実行できます。

まとめ

cssやjsの外部ファイルが原則使えないため、1ページ内でcssも書かないといけません。 ただそうすると、通常版のhtmlと同じcssが使えなくなったり、 scssを使ったら、手書きでコピペなどしないといけなくなってしまい、 手間が増えてしまいます。

また、今回は省いていますが、最終的にできたものに amp-validationを通すといったこともできます。

自分もまだ、本日紹介した方法以外にもいい方法が無いかな~とか調べていたりするのですが、 ひとまず小さく小さいページで試していきたいとかなら、こういったツールの組み合わせで、 通常のhtmlとcssと画像が共有できるので、運用しやすいかと思います。