.htaccessにページ単位での301リダイレクトを効率よく記述する。

新しいサイトを作ったので、旧サイトのコンテンツをサブドメインにお引越ししたいという状況になりました。
その場合はリダイレクト設定をしないと検索エンジンにそっぽを向かれてしまう恐れがあります。

301リダイレクトにはドメイン単位とかディリクトリ単位とかいろいろあります。

今回のケースだとページごとにひとつずつ設定するしかなさそうだったので、やった手順を書き残しておきます。

はじめに

サーバーはApacheです。いろいろ試した結果、私の環境では以下のコードできちんとリダイレクトできました。

RewriteEngine on
RewriteRule ^before.html$ https://ecco.co.jp/after.html [L,R=301]

引用元:https://ecco.co.jp/blog/htaccess-redirect/

※このとき気づいたのが、日本語URLはエンコードされているとリダイレクトしないので、デコードしておく必要がありました。

作業手順

設定が必要なURLを収集

  1. Screaming Frog SEO Spiderを使い対象ページを収集。
  2. 収集したURLをCSV形式でダウンロードし、Googleスプレッドシードにアップ。
  3. フォーマットに沿った形に文字列を連結する。
  4. .htaccessに転記してアップ。実際の挙動を確認。

(1)Screaming Frog SEO Spiderを使い、サイトの全ページを取得し、投稿ページのみリダイレクト対象としてCSVファイルにエクスポートしました。


Screaming Frog SEO Spider とは?

海外製のアプリで、サイトをクロールしSEOに必要な各種データを取得できる便利なツールです。

(2)Googleスプレッドシードにアップし、不要なデータを削除。リダイレクト先のURL一覧を作ります。

(3)フォーマットに沿った形になるように文字列を連結します。(画像参照)
ScreamingFrogSEO Spiderのスクリーンショット

(4)コードが完成したら、.htaccessに記載しサーバーにアップ。
ブラウザからアクセスし、正しくリダイレクトできているか確認。

以上です!

【2019年6月】Node.js/npm-scriptsでWordPressのテーマ開発環境を構築。(ライブリロードあり)

WordPressのテーマ作成用のGulp開発環境をしばらく放置してしまい、gulpと各種プラグイン、Node.js本体をバージョンアップしたところエラーが多発してビルドできない状況になってしまいました。

これを機に、以前からやってみたかったnpm-scriptsによるビルド環境に移行することにしました。本記事は、その時実施した内容の備忘録です。

実装した機能

  • PHPファイル、画像ファイル、npm管理外のプラグイン/ライブラリファイル等をsrcからdistにコピー
  • テーマファイルを削除
  • sassのコンパイル(ワイルドカードも可)
  • cssにベンダープレフィックス付与
  • JavaScriptをES5に変換してバンドル(rollup.js使用)
  • JS/CSSをフォーマット(prettier使用)
  • ファイルを監視→WPのテーマディリクトリに出力→ライブリロード
ご注意

※本記事はMacで検証しています。package.jsonのconfigの値を参照する記法がwindowsの場合は異なるという情報がありますが、未検証なのでご注意ください。

※WordPressのローカル環境構築は割愛しています。あらかじめdistディリクトリに設置し、起動できる前提としています。筆者はMAMPを使っています。

※ライブリロードは、WordPressを動作させるローカルサーバー(この記事ではMAMP)をbrowser-syncで連携させることにより利用できる前提です。

ディリクトリ構成

theme-dev/
 ├ dist/ *WordPressを設置
 ├ src/
  ├ package.json
  ├ rollup.config.js *rollup.jsの設定ファイル
  ├ bs-config.js *browser-syncの設定ファイル
  ├ php/ *WordPressのテーマで使うphpファイルはここにまとめて設置。
  ├ public/ *npmで配布されていないライブラリなどはここに設置。
  ├ images/
  └ assets/
    ├ js/
    └ sass/

一式まとめた圧縮ファイルはこちら

package.json作成

$ npm init

パッケージのインストール

ファイルのコピー/削除

$ npm install cpx --save-dev
$ npm install rimraf --save-dev

sassコンパイル/sassワイルドカード

$ npm install node-sass --save-dev
$ npm install node-sass-globbing --save-dev

ベンダープレフィックス追加

$ npm install postcss-cli autoprefixer --save-dev

JS ES5変換/バンドル

$ npm install rollup --save-dev
$ npm install rollup-plugin-node-resolve rollup-plugin-commonjs rollup-plugin-babel --save-dev
$ npm install @babel/core @babel/preset-env --save-dev

コードフォーマッタ

$ npm install prettier --save-dev

スクリプトの直列/並列実行

$ npm install npm-run-all --save-dev

ファイル監視/ライブリロード

$ npm install watch --save-dev
$ npm install browser-sync --save-dev

設定ファイルの作成

ルートディリクトリに下記設定ファイルを設置。

rollup.config.js

import resolve  from 'rollup-plugin-node-resolve';
import commonjs from 'rollup-plugin-commonjs';
import babel  from 'rollup-plugin-babel';

export default {
  input: 'src/assets/js/script.js',
  output: {
    format: 'iife',
    dir: 'dist/wp-content/themes/theme-dev' //テーマファイルを出力したいパスを指定
  },
  plugins: [
    resolve({
      jsnext: true
    }),
    commonjs(),
    babel({
      presets: [
        [
          "@babel/preset-env", {
          "modules": false,
          "targets": {
            "browsers": ['last 2 versions']
          }
        }
        ]
      ],
      babelrc: false
    })
  ],
  experimentalCodeSplitting: true
};

bs-config.js

※MAMP等でサーバーを起動したときにWordPressサイトが動作するURLをproxyに記載します。

module.exports = {
    "proxy": "http://localhost:8888/theme-dev/dist/" //MAMP等のローカルサーバーを指定
};

package.jsonにnpm-scriptsを追加

※configとscriptsのみ掲載します。
※distPathはテーマファイルを出力したいパスを指定します。

  "config": {
    "distPath": "/dist/wp-content/themes/theme-dev",
    "sassIndex": "/src/assets/sass/style.scss"
  },
  "scripts": {
    "clean": "rimraf .$npm_package_config_distPath",
    "copy/php": "cpx 'src/php/**/*.php' .$npm_package_config_distPath",
    "copy/public": "cpx 'src/public/**/*' .$npm_package_config_distPath/public",
    "copy/image": "cpx src/images/*/ .$npm_package_config_distPath/images",
    "copy": "npm-run-all -p copy/*",
    "css/sass": "node-sass --importer node_modules/node-sass-globbing/index.js .$npm_package_config_sassIndex -o .$npm_package_config_distPath --output-style expanded --source-map .$npm_package_config_distPath",
    "css": "npm-run-all -s css/*",
    "js/rollup": "rollup -c=rollup.config.js",
    "js": "npm-run-all -s js/*",
    "fmt/js": "prettier --write src/assets/js/*.js",
    "fmt/sass": "prettier --write src/assets/sass/**/*.scss",
    "fmt": "npm-run-all -p fmt/*",
    "build": "npm-run-all -s clean copy/* css js fmt",
    "dev/server": "browser-sync start --config bs-config.js --files=.$npm_package_config_distPath/*.css, .$npm_package_config_distPath/*.js, .$npm_package_config_distPath/**/*.php",
    "dev/css": "watch 'npm run css' src/assets/sass/",
    "dev/js": "watch 'npm run js' src/assets/js/",
    "dev/php": "watch 'npm run copy' src/php/",
    "dev/image": "watch 'npm run copy' src/images/",
    "dev/fmt": "watch 'npm run fmt' src/assets/js/ src/assets/sass/**/",
    "dev": "npm-run-all -p build dev/*",
    "prd/sass": "node-sass --importer node_modules/node-sass-globbing/index.js .$npm_package_config_sassIndex -o .$npm_package_config_distPath --output-style expanded",
    "prd/postcss": "postcss .$npm_package_config_distPath/style.css -o .$npm_package_config_distPath/style.css",
    "prd": "npm-run-all -p prd/*",
    "release": "npm-run-all -s clean copy prd js fmt"
  },


※configのdistPathにはテーマファイルを出力したいパスを指定します。

使用できるコマンド

開発用ビルド

$ npm run build

開発用ライブリロード

$ npm run dev


※このコマンドでエラーが起きる場合はいったんnpm run buildしてみてください。

本番用ビルド

$ npm run release

PHPファイル、画像ファイル、任意のプラグイン/ライブラリファイル等をsrcからdistにコピー

$ npm run copy

テーマファイルを丸ごと削除

$ npm run clean

まとめ

CSS/JSの圧縮は今回見送りました。webpackを使うと良いのかもしれません。

また、lint系のプラグインも入れてません。この辺はエディタ任せでもいいかと思いつつ、気が向いたら試すかなー?という感じです。

Local by Flywheelとの連携も試しました。browser-syncの監視対象をカンマ区切りで複数指定すると、ファイルを編集してないのに勝手にリロードするという現象が発生しましたが、カンマ区切りやめてアスタリスクで全ファイル指定したら大丈夫そうでした。


以下の記事を参考にさせていただきました。(ありがとうございました)

[WordPress]タクソノミーのタームが増えたらリンクが動的に新しいタームへ切り替わるナビゲーションの作り方。

2016年、2017年、2018年というような「年度」をカスタムタクソノミータームとした、毎年タームが増えていくWordPressサイトを作った時のメモです。

グローバルメニューの中に「最新年度のカスタムタクソノミーアーカイブページヘのリンク」が必要で、年度が変わってタームが増えたら自動的に最新年度ページへのリンクを出力する仕組みが必要になりました。

今年が2016年だったとして、来年になったら自動的に2017年のカスタムタクソノミータームアーカイブページへリンクを切り替えたいわけです。

仕様として、カスタムタクソノミーは「year」、タームは前述のように「年度」、タームスラッグは「西暦」とします。

term-sample

コードを以下のように作りました。

<ul>
<?php
/**
 * カスタムタクソノミー「year」のタームアカーイブページヘのリンクを動的に表示させる
 * 仕様としてカスタムタクソノミーのスラッグは西暦を使っていて、西暦を降順で取得し、一つ目のデータからリンクを生成する
 */

//ソートの仕方を指定
$args = array(
    'hide_empty' => 0, // デフォルトでは投稿を持っていない(空の)タームを返さない。 0=falseを指定すると返す。
    'orderby' => 'slug',
    'order' => 'DESC'
);

//ソートしたタームの配列を取得
$terms = get_terms( 'year', $args);

//最新の西暦のタームへのリンクを出力
echo '<li class="menu-item"><a href="';
echo home_url() . '?taxonomy=year&term=' . $terms[0]->slug . '/'; //ソートしたタームの一つ目からurlを生成
echo '">最新の西暦</a></li>';

?>
</ul>

タクソノミー「year」のターム「西暦」の最新を取得するために、get_terms()でターム情報が入ったオブジェクトを取得し、「最新の西暦」であるタームを取得するためにタームスラッグを降順でソート。タームスラッグを西暦にしてあるので、新しい年が常にオブジェクトの一番目に来ます。

取得したターム「最新の西暦」の名前とスラッグを組み合わせてリンクを生成します。

※get_terms()で以下のようなオブジェクトが取得できます。
term-array

get_terms()の二番目の引数のオプションに「hide_empty」というのがあるのですが、これでハマりました。デフォルトではtrueになっているのですが、そのままだと「タームは作ったけど投稿はまだ無い」という場合に、オブジェクトの中に入ってきません。場合によっては$terms[0]->slugで取りたくても[0]が無い!という状況になってしまいます。

うまくいかない時はこのオプションに注意したほうが良さそうです。

jQuery.ajax()を使ってクリックイベントで投稿を取得。WP REST APIを試してみました。

JSON形式のデータを取得できるWP REST APIというWordPressプラグインを使ってクリックイベントでWordPressの投稿を取ってくるサンプルコードを作成しました。

このプラグインを使ってサイトのホームのurl+/wp-json/wp/v2にアクセスするとJSON形式のデータが返却される機能が提供されます。更にパラメータを追加してWP_Queryのように投稿を取得することもできます。このデータを利用して、以下の様な記述で投稿を取得できました。

demo

JavasScript(jQuery)

//最新の投稿6件を取得するスクリプト
jQuery(function() {
 
//jsonデータが返却されるurl
var APIurl = 'https://stella-design.biz/wp-json/wp/v2/posts/?filter[posts_per_page]=6';
 
//投稿データ表示
jQuery('.btn-api-load').on('click', function(){
	jQuery('.api').empty().removeClass('fade-in');
	jQuery('.loading').removeClass('hidden');
	setTimeout(function(){
		ajaxGetPost();
	},2000);
});
 
//投稿データ取得 
function ajaxGetPost(){
	jQuery.ajax({
		type: "GET",
		url: APIurl,
		dataType: "json"
	})
	.then(
		function(json){
			for(var i in json){
				jQuery('.api').append('
  • ' + json[i].title.rendered + '
  • '); } }, function(){ alert("データをロードできませんでした。"); } ); jQuery(document).ajaxStop(function(){ jQuery('.loading').addClass('hidden'); jQuery('.api').addClass('fade-in'); }); } });//jQuery end

    html

    
    <button class="sd-btn btn-api-load">click</button>
    <div class="develop-block">
        <ul class="ul api"></ul>
        <div class="loading hidden">loading</div>
    </div>
    

    css

    
    @-webkit-keyframes ani-opa {
    	0% {
    		opacity: 0;
    	}
    	50% {
    		opacity: 1;
    	}
    	100% {
    		opacity: 0;
    	}
    }
    @keyframes ani-opa {
    	0% {
    		opacity: 0;
    	}
    	50% {
    		opacity: 1;
    	}
    	100% {
    		opacity: 0;
    	}
    }
     
    .loading {
    	margin: 15px 0;
    	-webkit-animation: ani-opa 1s infinite;
    	animation: ani-opa 1s infinite;
    }
     
    .hidden {
      visibility: hidden;
    }
     
    .api {
    	opacity: 0;
    	-webkit-transition-property: opacity;
    		  transition-property: opacity;
    	-webkit-transition-duration: 2s;
    		  transition-duration: 2s;
    	-webkit-transition-timing-function: ease;
    		  transition-timing-function: ease;
    	-webkit-transition-delay: 0.1s;
    		  transition-delay: 0.1s;
    }
     
    .fade-in {
    	opacity: 1;
    }
    
    .btn-api-load{
    	margin-top: 15px;
    }
    
    .develop-block{
    	padding: 30px 0;
    }
    

    昨年春のマット・マレンウェッグ氏のイベントによると、WP REST APIがWordPressのコアにマージされる時期が近づいているようです。

    JavaScriptを使ってスマートフォンネイティブアプリに近いUIを備えたwebサイトは今後ますます増えていくと個人的には思っています。その流れに対応できるよう、今年は昨年以上にがっちりJavaScriptに取り組んで行く予定です。

    しかしながら、JavaScriptをやればやるほど、サーバーサイドスクリプトの知識の必要性を感じるようになりますね。両方出来たほうがよりよいものが作れる。ひとまずはPHPももっとがんばって、WEBサービス的なものを作れるようになれたらいいな、と思い始めています。

    これでいいのか?WordPress制作のワークフロー

    いきなりですが、このエントリーを読んでいる方に質問です。WordPressのテーマを仕事で作成する際に、どのようなワークフロー、制作手順でコーディング・構築・テーマ作成を進めますか?

    デザインから WordPress のテーマ作成までの自分のワークフローを見直す – HAM MEDIA MEMO

    北海道札幌で活動されているフリーランスのフロントエンジニア「ハム」さんのブログでこんな問いかけがあったので反応してみました。

    ひとまず、自分の守備範囲から。

    WEBデザイン、HTML/CSSコーディング、JavaScriptの実装(あんま難しくないヤツ)、WordPressの構築とカスタマイズ、テーマ作成、場合によってはコンテンツのライティングや写真撮影、画像補正やちょっとしたイラスト作成もやります。分業せずに、頭から終わりまで一貫して受け持つパターンが多いです。

    守備範囲は広めながら、これ極めました!と言えるところがない中途半端な感じで悲し…(ちなみに一番好きなのはCSSコーディングです。JavaScriptも楽しい!)

    で、実際の制作案件ではWordPressを導入することがほとんど。なんでもかんでもWPってどうよ?という話はあるのですが、実際、もう静的HTMLの作り方を忘れるくらいどっぷりWordPressに浸かっています。(や、好きなのでいいのですが。)

    で、ワークフローは?

    トップページのデザイン案があらかじめ出ていることが前提となります。自分で作ったり、他の人が作ったり。そしてその後の流れ。

    1. 要件定義、仕様策定。
    2. ほぼ素の状態のWordPressを構築。コンテンツを流し込んで整理。課題問題を浮き彫りにします。
    3. ある程度形になったところで、必要に応じてPhotoShopやIllustratorでカンプ作成やデザインパーツ追加。
    4. WordPrssのテーマ作成。同時にプラグインの実行テストとJavaScriptの実装を行います。

    いわゆるCMSプロトタイピングの手法を取り入れています。2~4の工程をぐるぐる回しながら、クライアントや営業に確認をとって徐々に完成度を高めていく感じです。

    (しかし…ヒアリングなし、当てずっぽうでトップページデザイン作ってページ構成も適当でそのままなんとなくWP構築…なんてことをやるハメになることも多いです…それはいかんハズだろ…)

    いきなりテーマ作成?その前に静的ファイルを作る?

    その人が持つスキルやフローによって最適解が大きく変わると思いますが、自分の場合はいきなりテーマファイル作ります。そもそもWordPressを利用することがほとんどなので、静的HTMLの出番が無いのです…JekyllとかMiddlemanとか機会があれば使ってみたいです。

    WordPressの環境構築に関しては、vccwとかエレガントなものは使ってません。XAMPPで消耗しながら間に合わせてます。

    固定ページ問題

    コーディング時のフローで管理画面の登録フローがはいってしまうのはワークフローは、確実に手間になるのではないかと。

    これはキタジマさん僕の WordPress テーマ制作のワークフロー ( 仕事編 ) – Habakiriでも言及していますが、自分も同意です。

    自分の対処方法としては、BootStrapのグリッドレイアウトで汎用的なレイアウトパターンを組むことに加え、bodyclassを利用してSassでゴリ押しすることでしょうか。

    htmlにはなるべく手を加えずにBootStrapでレイアウトをパターン化し、bodyClassを接頭辞としてスコープを作りつつ、Sassでモジュール化したmixinを使いまわして活用することを意識してます。ある程度はまではなんとかなってます。

    CSSが複雑になりがちですが、管理画面にhtmlを修正しに行くことに比べればいくらかマシかなと。あとはSassの使いこなしや命名規則を洗練させて、少しでもメンテナブルなCSSを目指すことも欠かせません。

    フルスクラッチorスターターテーマ?

    テーマの作成において

    • 何もないところからスタート(フルスクラッチ)
    • 既存や自作のテーマを利用してスタート

    テーマをゼロから作るのか、既存のテーマを土台にしたり、子テーマを利用するフローが良いのかということですが、自分は自作テーマをベースにしてそこからスクラッチしてます。子テーマにもしてません。

    自分のスキルレベルとあまりに乖離したテーマをカスタマイズしようとしても、難しくてかえって工数が膨らんでしまうという悲しい出来事が起こってしまいます…

    自分のスキルレベルの変遷にあわせてテーマを乗り換える必要が出るでしょうし、そうなったらなかなか大変そう。既成テーマがずっとメンテされ続ける期待を持つのもどうかと。

    それならフルスクラッチでも自作テーマでもその時点で自分が把握する範囲のものを使った方が自分の勉強にもなるし、いいかなと思ってしまいます。

    ただ、自分の場合はそろそろ考え方を変えてもいい時期がきたと思っています。前述の問題点は、Habakiriならクリアできそうな気がしてます。

    自分より力量が上の人が作ったテーマを勉強させてもらうことはスキルアップにつながりますし、どこかのタイミングでHabakiriを使わせてもらう考えでいます。

    子テーマに関しては、親となる自作のテーマの作りこみが十分なレベルに達していなかったこともあり、見送り続けてきました。今後は機会があれば取り入れてみて、試すところから始めて見たいと思っています。

    追記:2016/6/23
    うーん、やっぱり子テーマは苦手だ…

    まとめ

    ワークフローが主題でしたが、うんちく的な部分の方が多くなってしまいました。万人に共通してこれが最適というフローはなかなか無いかもしれませんが、ハムさんやキタジマさんのエントリーは大いに参考になりました。ありがとうございました!

    WP REST API(WordPress JSON REST API )について調べてみました。

    最近、WP REST APIが気になっています。

    WordPress › WP REST API (WP API) « WordPress Plugins

    近い将来WordPressのコアにマージされるらしいWordPress JSON REST API を、先行してプラグインの形で提供しているものらしいです。

    このプラグインを使うとWordPressのデータにアクセスして、JSON形式でデータを取得することができるらしく、WordPressのテーマをHTMLとJavaScriptだけで作ることが可能だったり、スマフォアプリや様々なプラットホームにデータを配信できたりするらしいです。

    しかしながら、APIの実装をやったことがないので、勉強がてら少し調べてみました。

    そもそもAPIとは?

    Application Programming Interface(アプリケーション プログラミング インターフェース)の略語。

    APIとは、あるコンピュータプログラムソフトウェア)の機能や管理するデータなどを、外部の他のプログラムから呼び出して利用するための手順やデータ形式などを定めた規約のこと。

    個々のソフトウェアの開発者が毎回すべての機能をゼロから開発するのは困難で無駄が多いため、多くのソフトウェアが共通して利用する機能は、OSミドルウェアなどの形でまとめて提供されている。そのような汎用的な機能を呼び出して利用するための手続きを定めたものがAPIで、個々の開発者はAPIに従って機能を呼び出す短いプログラムを記述するだけで、自分でプログラミングすることなくその機能を利用したソフトウェアを作成することができる。

    近年ではネットワークを通じて外部から呼び出すことができるAPIを定めたソフトウェアも増えており、遠隔地にあるコンピュータの提供する機能やデータを取り込んで利用するソフトウェアを開発することができる。

    APIとは|アプリケーションプログラミングインターフェース|Application Programming Interface – 意味/解説/説明/定義 : IT用語辞典

    じゃあRESTは?

    RESTとは、2000年にRoy Fielding氏が提唱した、分散システムにおいて複数のソフトウェアを連携させるのに適した設計原則の集合。また、狭義には、それをWebに適用したソフトウェアの設計様式のこと。一般には後者の意味で用いられることがほとんどである。

    一般によく使われる狭義のRESTは、パラメータを指定して特定のURLにHTTPでアクセスすると、XMLで記述されたメッセージが送られてくるようなシステムおよび呼び出しインターフェース(「RESTful API」と呼ばれる)のことを指す。システムの状態やセッションに依存せず、同じURLやパラメータの組み合わせからは常に同じ結果が返されることが期待される。ただし、厳密な技術的定義が共有されているわけではなく、「SOAPやRPCなどを必要としない、XMLベースの単純なWebインターフェース」くらいの意味で用いられる場合が多い。

    RESTとは|REpresentational State Transfer – 意味/解説/説明/定義 : IT用語辞典

    何を作る?

    まずはajaxを使って、ページ遷移無しで投稿データをとってきて表示させたい。1ページで完結するようなウェブアプリのようなものをそれらしく作れないでしょうか。

    そんな感じでWordPressのREST APIを覚えていきたいですね。ぐるなびやらはてなやらkintoneやらいろいろAPIがあるので、いろいろなAPIを使うためのいい勉強になると思います。