はじめに
この記事は以下のような方の手助けになるかもしれません。
- webpack3で開発環境を作りたいけどうまく作れない
- sass + autoprefixer をいれて開発したい
- ためしにwebpackを使って見たい
エンジニア歴が浅いので、あまり信用しすぎずにお願いします。
(もっとこうしたほうがいいよ!というアドバイスお待ちしております)
ディレクトリ構造
.
├── package-lock.json
├── package.json
├── postcss.config.js
├── script
│ └── shell-scripts
│ └── release.sh
├── src
│ ├── assets
│ │ └── json
│ │ └── data.json
│ ├── index.html
│ ├── js
│ │ ├── config
│ │ │ ├── config.js
│ │ │ ├── development.js
│ │ │ └── production.js
│ │ ├── entry.js
│ │ └──module
│ │ └── sample.js
│ └── scss
│ ├── module
│ │ └── reset.scss
│ └── style.scss
└── webpack.config.js
configファイル
webpack周りの設定のためのファイルは以下の2つです。
- webpack.config.js
- postcss.config.js
また、今回は以下の package を使用しています。
package.json
{
"name": "web",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "rm -rf dest && NODE_ENV=development webpack-dev-server",
"build": "rm -rf dest && NODE_ENV=production webpack -p",
"build:release": "rm -rf dest && sh ./scripts/shell-scripts/release.sh && NODE_ENV=production webpack -p"
},
"author": "",
"license": "ISC",
"devDependencies": {
"autoprefixer": "^7.2.1",
"babel-core": "^6.26.0",
"babel-loader": "^7.1.2",
"babel-preset-es2015": "^6.24.1",
"babel-preset-react": "^6.24.1",
"copy-webpack-plugin": "^4.2.3",
"css-loader": "^0.28.7",
"extract-text-webpack-plugin": "^3.0.2",
"node-sass": "^4.7.2",
"postcss-loader": "^2.0.9",
"precss": "^2.0.0",
"sass-loader": "^6.0.6",
"style-loader": "^0.19.0",
"url-loader": "^0.6.2",
"webpack": "^3.10.0",
"webpack-dev-server": "^2.9.7"
}
}
webpack.config.js
const webpack = require('webpack');
const path = require('path');
const autoprefixer = require('autoprefixer');
const precss = require('precss');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const ENV = process.env.NODE_ENV;
module.exports = [
{
devtool: ENV === 'development' ? 'cheap-module-eval-source-map' : '',
devServer: {
contentBase: path.join(__dirname, 'dest'),
port: 6500,
},
entry: {
'bundle': path.join( __dirname, 'src', 'js', 'entry.js' )
},
output: {
path: path.join( __dirname, 'dest', 'js' ),
filename: '[name].js'
},
module: {
loaders: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
query: {
presets: ['es2015']
}
}
]
},
plugins: [
new webpack.ProvidePlugin({
'$' : 'jquery'
}),
new webpack.DefinePlugin({
'NODE_ENV': JSON.stringify(ENV),
'API_KEY' : JSON.stringify("KEY:XXX-XXX")
}),
]
},
{
entry: {
style: path.join( __dirname, 'src', 'scss', 'style.scss' )
},
output: {
path: path.join( __dirname, 'dest', 'css' ),
filename: '[name].css'
},
module: {
rules: [
{
test: /\.scss$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: ['css-loader', 'postcss-loader', 'sass-loader']
}),
exclude: /node_modules/
},
]
},
plugins: [
new ExtractTextPlugin('style.css'),
new CopyWebpackPlugin(
[
{
from: path.join( __dirname, 'src', 'assets'),
to: path.join( __dirname, 'dest', 'assets')
},
{
from: path.join( __dirname, 'src', 'index.html'),
to : path.join( __dirname, 'dest', 'index.html')
}
],
{ ignore: [ '.DS_Store', '*.js', '*.jsx', '*.scss', '*.css' ] }
),
]
}
]
webpackでsassをコンパイルしていい感じにするために、
そもそも設定を書き分けています。
javascriptをbundleするための設定と、sassやそのほかのアセットの
コピータスクなどを分けて書くことで
エントリーポイントを変に複雑にしなくていいので楽になりました。
もしreactなどを使う場合にはwebpack.ProvidePlugin
に
reactやreactDomなどを追加すると便利に使えます。
webpack-dev-serverの設定も入っているので、
開発するときもコマンド一発でスタートできるので
この設定はかなり気に入っています。
postcss.config.js
module.exports = {
plugins: {
'autoprefixer': {
browsers: ['last 2 versions', '> 2%']
}
}
}
pluginの設定です。webpack.config.jsの中に書きたかったのですが
うまくいかなかったので外に出して書きました。
srcファイル
以下は完全に蛇足ですが、動くかどうかを試す際に入れていたサンプルコードです。
src/js/entry.js
import Person from './module/sample.js';
import CONFIG from './config/config.js';
var human = new Person('nisshy');
human.sayHello();
entry.js で config やら module を読み込みます。
ES6の記法を試すためにconstructorを使って見ました。
src/js/module/sample.js
class Person {
constructor(name) {
this.name = name;
}
sayHello() {
console.log( "Hello, I'm " + this.getName() );
}
getName() {
return this.name;
}
}
export default Person
sample.jsでclassを定義してexport defaultしています。
src/js/config/config.js
const config = require( './' + NODE_ENV );
export default class Environment {
static get API_PATH() {
return config.API_PATH;
}
static get SITE_NAME(){
return config.SITE_NAME;
}
}
このconfigファイルは環境によって値を変えたいものを定義したいものを
読んでくるためのファイルです。
ここではテスト環境と本番環境でapiのpathが違うことを想定して、
development
とproduction
とで出し分けをしています。
(SITE_NAMEは単純にテストのために使って見ました)
webpackを実行する際に NODE_ENV=development
を指定すると、
require( './development ')
となり、developmentの設定を読んでくれます。
本番と開発を手作業で書き分けたりすると99.9%ミスを起こすので
初めからこんな感じでかき分けるようにしました。
src/js/config/development.js
const config = {
API_PATH: 'https://fizzbuzz.com/api/',
SITE_NAME: 'DEVELOPMENT SITE'
}
module.exports = config;
src/js/config/production.js
const config = {
API_PATH: 'https://foobar.com/api/',
SITE_NAME: 'PRODUCTION SITE'
}
module.exports = config;
最後に
少し余分な記述があったりしますが、開発を始める際のベースとしてのセットであれば
問題ないのかな?と思ってます。
個人的にはgulpよりもwebpackのほうがかっこいいなぁと思っているので
もう少し使い方を掘っていきたいと思います。