LoginSignup
35
35

More than 5 years have passed since last update.

ECMAScript6対応 webpackを最低限実務で使う為の設定とRailsとwebpackの共存方法

Last updated at Posted at 2016-10-28

やること

webpackとそのPluginを使って、実務で使えるレベルにするには、情報が断片的だったのでまとめてみました。

[追記]
Railsとwebpackの共存方法についても記述しました。

以下の事を実現する

ES6をES5に変換

  • babel-core
  • babel-loader
  • babel-preset-es2015

SCSSのコンパイル

  • css-loader
  • style-loader
  • extract-text-webpack-plugin
  • sass-loader
  • node-sass

JS内にHTMLファイルを読み込む

  • html-loader

Font Awesomeをnpmでインストール

  • file-loader
  • url-loader

ブラウザのLive Reload

  • browser-sync
  • browser-sync-webpack-plugin

.envでの設定値をセットし、process.envから取得できるようにする

  • dotenv

Productionビルド用にuglifyする

Productionビルド用にファイル名にハッシュをつける

  • assets-webpack-plugin

JSのシンタックスチェック

  • eslint
  • eslint-loader

npm package Install

npm install --save-dev babel-core babel-loader babel-preset-es2015 browser-sync browser-sync-webpack-plugin css-loader dotenv eslint eslint-loader extract-text-webpack-plugin file-loader node-sass sass-loader style-loader url-loader html-loader assets-webpack-plugin webpack

Babelの設定

.babelrc
{
  "presets": ["es2015"]
}

ESLintの設定

.eslintrc
{
    "env": {
        "browser": true,
        "es6": true,
        "jquery": true
    },
    "extends": "eslint:recommended",
    "parserOptions": {
        "sourceType": "module"
    },
    "globals": {
        "process": true
    },
    "rules": {
        "comma-dangle": [
            1,
            "only-multiline"
        ],
        "indent": [
            "error",
            2
        ],
        "quotes": [
            "error",
            "single"
        ],
        "semi": [
            "error",
            "never"
        ]
    }
}

webpackの設定

webpack.config.js
var path = require('path')
var webpack = require('webpack')
var ExtractTextPlugin = require('extract-text-webpack-plugin')
var BrowserSyncPlugin = require('browser-sync-webpack-plugin')
var AssetsPlugin = require('assets-webpack-plugin')

require('dotenv').config()

const isProduction = (process.env.NODE_ENV === 'production')

var assets = new AssetsPlugin({
  filename: 'webpack-asset-manifest.json',
  includeManifest: 'manifest',
  prettyPrint: true
})
var defineEnv = new webpack.DefinePlugin({
  'process.env': {
    'NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development'),
    'HELLO_WORLD': JSON.stringify(process.env.HELLO_WORLD)
  }
})
var uglify = new webpack.optimize.UglifyJsPlugin({ compress: { warnings: false } })
var extractText = new ExtractTextPlugin('style-bundle.css')
var browserSync = new BrowserSyncPlugin({
  host: 'localhost',
  port: 3001,
  server: { baseDir: ['public'] },
  files: ['src/*.css', 'src/*.js', 'public/*.html']
}, { reload: true })
var jsPlugins = isProduction ? [defineEnv, uglify, assets] : [defineEnv, browserSync, assets]
var cssPlugins = isProduction ? [extractText, uglify, assets] : [extractText, browserSync, assets]

var build_path = {
  js: 'public/assets',
  css: 'public/assets'
}

var devTool = isProduction ? '' : 'source-map'

const config_for_js = {
  entry: {
    'app': './main.js'
  },

  output: {
    path: path.join(__dirname, build_path.js),
    filename: isProduction ? '[name]-bundle-[hash].js' : '[name]-bundle.js'
  },

  context: path.resolve(__dirname, 'src'),

  module: {
    preLoaders: [
      { test: /\.js$/, loader: "eslint-loader", exclude: /node_modules/ }
    ],
    loaders: [
      { test: /\.js$/, exclude: /node_modules/, loaders: ['babel'] },
      { test: /\.html$/, loader: 'html' }
    ]
  },

  resolve: {
    root: [ path.resolve(__dirname, 'src') ]
  },

  devtool: devTool,

  plugins: jsPlugins
}

const config_for_static = {
  entry: [
    './src/scss/style.scss',
    'font-awesome/scss/font-awesome.scss'
  ],

  output: {
    path: path.join(__dirname, build_path.css),
    filename: isProduction ? '[name]-bundle-[hash].css' : '[name]-bundle.css'
  },

  module: {
    loaders: [
      { test: /\.css$/, loaders: [ 'style', 'css' ] },
      { test: /\.scss$/, loader: ExtractTextPlugin.extract('style', 'css!sass') },
      { test: /\.woff(\?v=\d+\.\d+\.\d+)?$/, loader: 'url?limit=10000&mimetype=application/font-woff' },
      { test: /\.woff2(\?v=\d+\.\d+\.\d+)?$/, loader: 'url?limit=10000&mimetype=application/font-woff' },
      { test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, loader: 'url?limit=10000&mimetype=application/octet-stream' },
      { test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, loader: 'file' },
      { test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, loader: 'url?limit=10000&mimetype=image/svg+xml' }
    ]
  },

  plugins: cssPlugins,

  devtool: devTool
}

module.exports = [config_for_js, config_for_static]

ソース

main.js
import HelloWorld from 'templates/hello_world.html'
import _ from 'lodash'
import $ from 'jquery'

const template = _.template(HelloWorld)
$('body').append(template({ title: process.env.HELLO_WORLD }))
templates/hello_world.html
<h1><a href="/another_page.html"><%= title %></a></h1>

↓↓↓↓↓↓↓↓↓↓ あと参考までに ↓↓↓↓↓↓↓↓↓↓

webpack-dev-serverかbrowser-syncのどちらを選択するか

BrowerとのSyncにはwebpack-dev-serverという選択肢もありますが、HTMLが1枚しか対応していないのでSPAを開発する場合にはよいが

SPAではなく、複数のHTMLで構成されてて、そのHTML間を遷移させて開発する場合にはbrowser-syncを使うしかないかなと思います。

webpack起動時に環境変数の内容でHTMLの中身を書き換えたい時

string-replace-loaderが便利でした。

webpack.config.jsには以下の設定をして

webpack.config.js
module.exports = {
  // ...
  module: {
    loaders: [
      { test: /index\.html$/, 
        loader: 'string-replace', 
        query: { 
          multiple:[
            { search: '$REPLACE_STRING', 
              replace: process.env.REPLACE_STRING 
            }
          ]
        } 
      }
    ]
  }
}

HTML内には設定で指定した文字列を埋め込んでおくと置換してくれる

index.html
<div class="$REPLACE_STRING">

Railsとwebpackの共存方法

css, javascriptのコンパイルなどはwebpackで完結したい場合、assets-webpack-pluginを使うと簡単に実現できます。

config/initializers/webpack.rb
Rails.configuration.webpack = {
  asset_manifest: {},
  asset_host: 'http://localhost:3000' # public/assets以下はs3に置く事を想定
}

asset_manifest = Rails.root.join('webpack-asset-manifest.json')
if File.exist?(asset_manifest)
  Rails.configuration.webpack[:asset_manifest] = JSON.parse(File.read(asset_manifest),).with_indifferent_access
end
app/helpers/application_helpers.rb
module ApplicationHelper
  def webpack_stylesheet_link_tag(name)
    stylesheet_link_tag(webpack_assets('css', name))
  end

  def webpack_javascript_include_tag(name)
    javascript_include_tag(webpack_assets('js', name))
  end

  private
    def webpack_assets(type, name)
      @manifest ||= Rails.configuration.webpack[:asset_manifest]
      host = Rails.configuration.webpack[:asset_host]
      return "#{host}/assets/#{@manifest[name][type]}"
    end
end

モダンなJavaScript開発を学べるおすすめの本

35
35
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
35
35