Gulp + Webpack

Для разработки приложений на React желательна поддержка модулей es6. Gulp c этой задачей самостоятельно не справляется. Для таких задач существует Webpack и Browserify. Рассмотрим работу с Webpack 2 и объединим его с Gulp. Webpack будет выполнять все задачи по JavaScript, а Gulp все остальное. Конфиги составлялись для работы с React, но могут быть использованы в других целях.

Сам gulpfile.

//gulpfile.js

'use strict';

let gulp     = require('gulp'),
    webpack  = require('webpack'),
    gutil    = require('gulp-util'),
    notifier = require('node-notifier'),
    path = require('path');

let less = require('gulp-less'),
    cleanCSS = require('gulp-clean-css'),
    autoprefixer = require('gulp-autoprefixer');

let webpackConfig = require('./webpack.config.js');
let statsLog      = { // для красивых логов в консоли
    colors: true,
    reasons: true
};

function swallowError(error){
    console.log(error.toString());
    this.emit('end');
}

gulp.task('default', ['gulp_watch']);

gulp.task('gulp_watch', function () {
    gulp.watch('./src/less/**/*.less', ['less']);
    gulp.watch('./src/js/**/*.js', ['scripts']);
    gulp.watch('./src/js/**/*.jsx', ['scripts']);
});

gulp.task('less', function () {
    return gulp.src('./src/less/main.less')
        .pipe(sourcemaps.init())
        .pipe(less({
            paths: [
                path.join(__dirname, 'less'),
                'bower_components'
            ]
        }))
        .on('error', swallowError)
        .pipe(autoprefixer({
            browsers: ['last 5 versions', '> 5%'],
            cascade: false
        }))
        .pipe(cleanCSS())
        .pipe(rename('style.css'))
        .pipe(sourcemaps.write('./'))
        .pipe(gulp.dest('./dist/css'));
});

gulp.task('scripts', (done) => {

    console.log(done);

    function onError(error) {
        let formatedError = new gutil.PluginError('webpack', error);

        notifier.notify({ // чисто чтобы сразу узнать об ошибке
            title: `Error: ${formatedError.plugin}`,
            message: formatedError.message
        });

        done(formatedError);
    }

    function onSuccess(detailInfo) {
        gutil.log('[webpack]', detailInfo);
        done();
    }

    function onComplete(error, stats) {
        if (error) { // кажется еще не сталкивался с этой ошибкой
            onError(error);
        } else if ( stats.hasErrors() ) { // ошибки в самой сборке, к примеру "не удалось найти модуль по заданному пути"
            onError( stats.toString(statsLog) );
        } else {
            onSuccess( stats.toString(statsLog) );
        }
    }

    // run webpack
    webpack(webpackConfig, onComplete);

});

Конфиг для webpack 2. Настройки less и css именно в этом файле не обязательны. Так как стилями занимается gulp.

//webpack.config.js
'use strict';

const path = require('path');
const webpack = require('webpack');

module.exports = {
    context: path.resolve(__dirname, './src'),
    entry: {
        app: './js/main.js'
    },
    output: {
        path: path.resolve(__dirname, './dist/js'),
        filename: 'bundle.js'
    },
    devtool: 'source-map',
    resolve: {
        extensions: ['.js', '.jsx', '.json']
    },

    module: {
        loaders: [
            {
                test: /\.js$/,
                exclude: /node_modules/,
                loader: "babel-loader",
                query: {
                    presets: ['es2015', 'react']
                }
            },
            {
                test: /\.jsx$/,
                loader: ["react-hot-loader", "babel-loader"],
                exclude: [/node_modules/, /dist/]
            },
            {
                test: /\.json$/,
                loader: "json-loader"
            },
            {
                test: /\.css$/,
                loader: "style-loader!css-loader!autoprefixer-loader",
                exclude: [/node_modules/, /dist/]
            },
            {
                test: /\.less$/,
                use: [ 'style-loader', 'css-loader', 'less-loader', 'autoprefixer-loader' ],
                exclude: [/node_modules/, /dist/]
            }
        ]
    },
    plugins: [
        new webpack.optimize.UglifyJsPlugin({
            compress: {
                warnings: false
            },
            sourceMap: true
        })
    ]
};

Этот файл может быть другим. Так как он составлялся для React с Redux. К тому же версии плагинов со временем меняются.

//package.json
{
  "name": "rtest",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "http-server ./dist -p 8000"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "autoprefixer-loader": "^3.2.0",
    "babel-core": "^6.24.1",
    "babel-loader": "^7.0.0",
    "babel-preset-es2015": "^6.24.1",
    "babel-preset-react": "^6.24.1",
    "css-loader": "^0.28.4",
    "gulp": "^3.9.1",
    "gulp-util": "^3.0.8",
    "json-loader": "^0.5.4",
    "less": "^2.7.2",
    "less-loader": "^4.0.4",
    "node-notifier": "^5.1.2",
    "react-hot-loader": "^1.3.1",
    "style-loader": "^0.18.2",
    "webpack": "^2.6.1"
  },
  "dependencies": {
    "axios": "^0.16.2",
    "material-ui": "^0.18.1",
    "react": "^15.5.4",
    "react-dom": "^15.5.4",
    "react-redux": "^5.0.5",
    "react-router-dom": "^4.1.1",
    "react-router-redux": "^5.0.0-alpha.6",
    "react-tap-event-plugin": "^2.0.1",
    "redux": "^3.7.1"
  }
}

Конфигурационный файл для babel

//.babelrc
{
  "presets": [
    "es2015",
    "react"
  ]
}
Share: