webpack3で作る開発環境(webpack + sass + autoprefixer)

More than 1 year has passed since last update.


はじめに

この記事は以下のような方の手助けになるかもしれません。


  • 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


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


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


postcss.config.js

module.exports = {

plugins: {
'autoprefixer': {
browsers: ['last 2 versions', '> 2%']
}
}
}

pluginの設定です。webpack.config.jsの中に書きたかったのですが

うまくいかなかったので外に出して書きました。


srcファイル

以下は完全に蛇足ですが、動くかどうかを試す際に入れていたサンプルコードです。


src/js/entry.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


src/js/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


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が違うことを想定して、

developmentproductionとで出し分けをしています。

(SITE_NAMEは単純にテストのために使って見ました)

webpackを実行する際に NODE_ENV=developmentを指定すると、

require( './development ')となり、developmentの設定を読んでくれます。

本番と開発を手作業で書き分けたりすると99.9%ミスを起こすので

初めからこんな感じでかき分けるようにしました。


src/js/config/development.js


development.js

const config = {

API_PATH: 'https://fizzbuzz.com/api/',
SITE_NAME: 'DEVELOPMENT SITE'
}

module.exports = config;



src/js/config/production.js


production.js

const config = {

API_PATH: 'https://foobar.com/api/',
SITE_NAME: 'PRODUCTION SITE'
}

module.exports = config;



最後に

少し余分な記述があったりしますが、開発を始める際のベースとしてのセットであれば

問題ないのかな?と思ってます。

個人的にはgulpよりもwebpackのほうがかっこいいなぁと思っているので

もう少し使い方を掘っていきたいと思います。