LoginSignup
3
4

More than 5 years have passed since last update.

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

Posted at

はじめに

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

  • 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のほうがかっこいいなぁと思っているので
もう少し使い方を掘っていきたいと思います。

3
4
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
3
4