Foundation6をLaravel Elixirで使用する2

タグ: Laravel5.1   Laravel5.2  

Foundation6をLaravel Elixirで使用する1では、Laravelのタスク自動化の機能を中心に利用しました。

Foundationはバージョン6になり、Gulpをフル活用した環境を提供するようになりました。画像の圧縮も用意されていますので、多少こちらのほうが便利です。Foundation6側の機能を中心に利用するケーススタディです。

方針

プロジェクトルート化にFoundation6プロジェクトを作成し、そちらでCSS、JS,画像などのリソースを管理します。(以下で紹介するコードの設定を変更すれば、Laravel側の'resources/assets'ディレクトリを使用することもできるでしょう。)

事前準備

真新しくLaravelプロジェクトを作成してください。

foundationコマンドをインストールしていない場合は、Foundationのインストールドキュメントに従い、用意してください。

ドキュメントのManual Installに記述されている手段でFoundationテンプレートをインストールする方法もありますが、LaravelプロジェクトがGitで管理されているかどうかにより手順は変わるでしょう。また、foundation newコマンドにより生成されるテンプレートと構造が同じかは確認していません。そのため、以降のファイルパスの調整が必要かもしれません。

Foundationプロジェクトの作成

Laravelプロジェクトルート下に、Foundationプロジェクトを作成します。プロジェクトルートでfoundation newコマンドを実行してください。後は以降に従い、プロンプトに答えてください。

    $ foundation new

    ? What are you building today? (Use arrow keys)
    ❯ A website (Foundation for Sites) # これを選択してEnter
      A web app (Foundation for Apps) 
      An email (Foundation for Emails)

    ? What's the project called? (no spaces) # foundation6 と入力しEnter

    ? Which template would you like to use? (Use arrow keys)
      Basic Template: includes a Sass compiler 
    ❯ ZURB Template: includes Handlebars templates and Sass/JS compilers # これを選択してEnter
                .
               /|     ,
          , /|/  \/| /|       Thanks for using ZURB Foundation for Sites!
         /|/       |/ |       -------------------------------------------
     |___|            |___|   Let's set up a new project.
     \___|  ^^   ^^   |___/   It shouldn't take more than a minute.
         | -[O]--[O]- |
         |    ___,    |
         |    ...     |
          \__________/


    Downloading the project template...
    Done downloading!

    Installing dependencies...

インストールが終了するまで数分かかります。

テンプレートではZURBテンプレートを選択しました。機能が豊富だからです。

Foundation6プロジェクトの準備

Foundation6のプロジェクトに入っているファイルを以下の内容へ修正してください。オリジナルのファイルは別名で保存しておきましょう。

config.yml
# Your project's server will run on localhost:xxxx at this port
PORT: 8000 

# Autoprefixer will make sure your CSS works with these browsers
COMPATIBILITY:
  - "last 2 versions"
  - "ie >= 9"

# UnCSS will use these settings
UNCSS_OPTIONS:
  html:
    - "src/**/*.html"
    # ビューファイルを追加
    - "../resources/views/**/*.php"
    # ビューのコンパイル結果を追加
    - "../storage/framework/views/*"
  ignore:
    - !!js/regexp .foundation-mq
    # - オリジナルは!!js/regexp ^\.is-.*だが、削除しすぎるため変更
    - !!js/regexp \.is-.*

# Gulp will reference these paths when it copies files
PATHS:
  # Path to dist folder
  dist: "dist"
  # Paths to static assets that aren't images, CSS, or JavaScript
  assets:
    - "src/assets/**/*"
    - "!src/assets/{img,js,scss}/**/*"
  # Paths to Sass libraries, which can then be loaded with @import
  sass:
    - "bower_components/foundation-sites/scss"
    - "bower_components/motion-ui/src"
  # Paths to JavaScript libraries, which are compined into one file
  javascript:
    # Libraries requried by Foundation
    - "bower_components/jquery/dist/jquery.js"
    - "bower_components/what-input/what-input.js"
    # Core Foundation files
    - "bower_components/foundation-sites/js/foundation.core.js"
    - "bower_components/foundation-sites/js/foundation.util.*.js"
    # Individual Foundation components
    # If you aren't using a component, just remove it from the list
    # Foundationコンポーネント中で使用しないものはコメントアウトしておく
    - "bower_components/foundation-sites/js/foundation.abide.js"
    - "bower_components/foundation-sites/js/foundation.accordion.js"
    - "bower_components/foundation-sites/js/foundation.accordionMenu.js"
    - "bower_components/foundation-sites/js/foundation.drilldown.js"
    - "bower_components/foundation-sites/js/foundation.dropdown.js"
    - "bower_components/foundation-sites/js/foundation.dropdownMenu.js"
    - "bower_components/foundation-sites/js/foundation.equalizer.js"
    - "bower_components/foundation-sites/js/foundation.interchange.js"
    - "bower_components/foundation-sites/js/foundation.magellan.js"
    - "bower_components/foundation-sites/js/foundation.offcanvas.js"
    - "bower_components/foundation-sites/js/foundation.orbit.js"
    - "bower_components/foundation-sites/js/foundation.responsiveMenu.js"
    - "bower_components/foundation-sites/js/foundation.responsiveToggle.js"
    - "bower_components/foundation-sites/js/foundation.reveal.js"
    - "bower_components/foundation-sites/js/foundation.slider.js"
    - "bower_components/foundation-sites/js/foundation.sticky.js"
    - "bower_components/foundation-sites/js/foundation.tabs.js"
    - "bower_components/foundation-sites/js/foundation.toggler.js"
    - "bower_components/foundation-sites/js/foundation.tooltip.js"
    # Paths to your own project code are here
    - "src/assets/js/!(app).js"
    - "src/assets/js/app.js"
gulpfile.babel.js
'use strict';

import plugins  from 'gulp-load-plugins';
import yargs    from 'yargs';
import browser  from 'browser-sync';
import gulp     from 'gulp';
import panini   from 'panini';
import rimraf   from 'rimraf';
import sherpa   from 'style-sherpa';
import yaml     from 'js-yaml';
import fs       from 'fs';

// Load all Gulp plugins into one variable
const $ = plugins();

// Check for --production flag
const PRODUCTION = !!(yargs.argv.production);

// Load settings from settings.yml
const { COMPATIBILITY, PORT, UNCSS_OPTIONS, PATHS } = loadConfig();

function loadConfig() {
    let ymlFile = fs.readFileSync('config.yml', 'utf8');
    return yaml.load(ymlFile);
}

// Build the "dist" folder by running all of the below tasks
gulp.task('build',
    gulp.series(clean, gulp.parallel(pages, sass, javascript, images, copy), styleGuide, copynewer));

// Build the site, run the server, and watch for file changes
gulp.task('default',
    gulp.series('build', server, watch));

// Delete the "dist" folder
// This happens every time a build starts
function clean(done) {
    rimraf(PATHS.dist, done);
}

// Copy files out of the assets folder
// This task skips over the "img", "js", and "scss" folders, which are parsed separately
function copy() {
    return gulp.src(PATHS.assets)
    .pipe(gulp.dest(PATHS.dist + '/assets'));
}

// Copy page templates into finished HTML files
function pages() {
    return gulp.src('src/pages/**/*.{html,hbs,handlebars}')
    .pipe(panini({
        root: 'src/pages/',
        layouts: 'src/layouts/',
        partials: 'src/partials/',
        data: 'src/data/',
        helpers: 'src/helpers/'
    }))
    .pipe(gulp.dest(PATHS.dist));
}

// Load updated HTML templates and partials into Panini
function resetPages(done) {
    panini.refresh();
    done();
}

// Generate a style guide from the Markdown content and HTML template in styleguide/
function styleGuide(done) {
    sherpa('src/styleguide/index.md', {
    output: PATHS.dist + '/styleguide.html',
    template: 'src/styleguide/template.html'
    }, done);
}

// Compile Sass into CSS
// In production, the CSS is compressed
function sass() {
    return gulp.src('src/assets/scss/app.scss')
    .pipe($.sourcemaps.init())
    .pipe($.sass({
        includePaths: PATHS.sass
    })
        .on('error', $.sass.logError))
    .pipe($.autoprefixer({
        browsers: COMPATIBILITY
    }))
    .pipe($.if(PRODUCTION, $.uncss(UNCSS_OPTIONS)))
    .pipe($.if(PRODUCTION, $.cssnano()))
    .pipe($.if(!PRODUCTION, $.sourcemaps.write()))
    .pipe(gulp.dest(PATHS.dist + '/assets/css'));
//    .pipe(browser.reload({ stream: true }));
}

// Combine JavaScript into one file
// In production, the file is minified
function javascript() {
    return gulp.src(PATHS.javascript)
    .pipe($.sourcemaps.init())
    .pipe($.babel())
    .pipe($.concat('app.js'))
    .pipe($.if(PRODUCTION, $.uglify()
        .on('error', e => { console.log(e); })
    ))
    .pipe($.if(!PRODUCTION, $.sourcemaps.write()))
    .pipe(gulp.dest(PATHS.dist + '/assets/js'));
}

// Copy images to the "dist" folder
// In production, the images are compressed
function images() {
    return gulp.src('src/assets/img/**/*')
    .pipe($.if(PRODUCTION, $.imagemin({
        progressive: true
    })))
    .pipe(gulp.dest(PATHS.dist + '/assets/img'));
}

// Start a server with BrowserSync to preview the site in
// 設定を直接指定している
function server(done) {
    browser.init({
        proxy: '127.10.10.10:' + PORT
    });
    done();
}

// ブラウザのリロード
// 終了を返さないと、watchが停止せず、次のファイル変更を補足できない
function reload(done) {
    browser.reload();
    done();
}

// Foundation側で処理したリソースファイルを
// Laravel環境へコピー
function copynewer(done) {
    gulp.src([
        PATHS.dist + '/assets/img/**/*',
        PATHS.dist + '/assets/css/**/*',
        PATHS.dist + '/assets/js/**/*'
        ], {base: PATHS.dist + '/assets'})
    .pipe(gulp.dest('../public'));
    browser.reload();
    done();
}

// Watch for changes to static assets, pages, Sass, and JavaScript
function watch(done) {

    // リソースの監視
    gulp.watch(PATHS.assets, gulp.series(copy));
    gulp.watch('src/assets/scss/**/*.scss', gulp.series(sass, copynewer));
    gulp.watch('src/assets/js/**/*.js', gulp.series(javascript, copynewer));
    gulp.watch('src/assets/img/**/*', gulp.series(images, copynewer));

    // 以下3監視は、Foundationの固定ページ生成
    // gulp.watch('src/pages/**/*.html', gulp.series(pages, copynewer, browser.reload));
    // gulp.watch('src/{layouts,partials}/**/*.html', gulp.series(resetPages, pages, browser.reload));
    // gulp.watch('src/styleguide/**', gulp.series(styleGuide, browser.reload));

    // Laravel側のファイルに変更が起きた時にもBrowserSyncをリロード
    gulp.watch([
            '../app/**/*.php',
            '../config/**/*.php',
            '../resources/**/*.php',
        ], reload);

    done();
}

今回はLaravel Elixirが提供するバージョン付け機能を使っていません。バージョン付けしたい場合は、Elixirで行ってください。Browserリロードのため、gulpfile.babel.jsの一番最後のwatchの対象に、'../public/build/rev-manifest.json'を追加します。

なお、Firefoxはリロード時にCSSの変更を捉えてくれますが、Chromeはデフォルト状態ではキャッシュにより更新されません。開発者ツールの'setting'(F1キー)の'General'タブ、一番最初の設定項目である"Disable cache (while DevTools is open)"にチェックを入れると、開発者ツールを開いている時のみキャッシュが無効になりますので、これを使うのがよいかと思います。

使用方法

foundation6ディレクトリでfoundation watchコマンドを実行すると、リソースの監視を行いつつ、必要なコンパイルやファイル結合が行われます。結果はBrowserSyncにより、自動的にブラウザへ再描写されます。

リソースは最終的にLaravelプロジェクトの'public'ディレクトリ下へコピーされます。出力場所を変更したい場合は、copynewer関数のdestメソッドの引数を変更します。

実働環境用の圧縮したバージョンのリソースを生成したい場合は、foundtion buildを実行します。