webpack+gulp 构建react项目

webpack,gulp,react

拭目以待 发布于

背景

GirdManager首页,使用 React 实现。 

需要实现功能

  1. jsx 转换为 js

  2. es6 转换为 es5

  3. 对文件进行合并、压缩

  4. 生成可供发布的zip包

  5. 单个页面只引入当前使用到的资源文件

为什么要将 webpack gulp 配合使用

webpack 在使用过程中, 并不能很好的解决文件相关的操作。所以采用 gulp 进行配合。 

webpack 与 gulp 各自实现的功能如下:

webpack

  1. jsx transform js

  2. es6 transform es5


gulp

  1. 文件操作

  2. 压缩html css js

  3. 生成发布所需zip包


实现源码

gulpfile.js

/*
* 文件操作
* 压缩html css
* 对js相关的操作使用webpack
* */
const gulp = require('gulp');
const htmlmin = require('gulp-htmlmin');
const minifyCss = require('gulp-minify-css');
const uglify = require('gulp-uglify');
const gulpIf = require('gulp-if');
const gulpUtil = require('gulp-util');
const zip = require('gulp-zip');
const del = require('del');
var miniHtmlOptions = {
    removeComments: true,  //清除HTML注释
    collapseWhitespace: true,  //压缩HTML
    collapseBooleanAttributes: false,  //省略布尔属性的值 <input checked="true"/> ==> <input checked />
    removeEmptyAttributes: true,  //删除所有空格作属性值 <input id="" /> ==> <input />
    removeScriptTypeAttributes: true,  //删除<script>的type="text/javascript"
    removeStyleLinkTypeAttributes: true,  //删除<style>和<link>的type="text/css"
    minifyJS: true,  //压缩页面JS
    minifyCSS: true  //压缩页面CSS
};
// 构建项目目录
var buildPath = 'GridManager';
// 打包后的名称
var zipName = 'GridManagerSite.zip';
var webpack = require('webpack');
var webpackConfig = require('./webpack.config.js');
// 默认执行
gulp.task('default', ['develop']);
// 构建开发包
gulp.task('develop', ['webpack:build']);
// 构建上线包
gulp.task('production', ['uglify'], function(){
    // gulp.start('uglify');
});
// 构造前: 删除原有构建包
gulp.task('clean', function() {
    del.sync([buildPath + '/*']);
});
// 构造前: 先删除之前的.zip
gulp.task('cleanzip', function(){
    del.sync(zipName);
});
// 移动文件,除jsx以外
gulp.task('movefile', ['clean', 'cleanzip'], function () {
    return gulp.src(['src/*app*/*/*', 'src/*assets*/*/*', 'src/index.html', '!src/**/*.js*'])
        .pipe(gulp.dest(buildPath));
});
// 压缩
gulp.task('uglify', ['webpack:build'], function(){
    return gulp.src([buildPath + '/**/*'])
        .pipe(gulpIf('*.html', htmlmin(miniHtmlOptions).on('error', gulpUtil.log)))
        .pipe(gulpIf('*.js', uglify().on('error', gulpUtil.log)))
        .pipe(gulpIf('*.css', minifyCss()))
        .pipe(gulp.dest(buildPath));
});
// 使用webpack 对jsx进行处理
gulp.task('webpack:build', ['movefile'], function(callback) {
    // modify some webpack config options
    var myConfig = Object.create(webpackConfig);
    // run webpack
    webpack(myConfig, function(err, stats) {
        if(err) throw new gutil.PluginError('webpack:build', err);
        gulpUtil.log('[webpack:build]', stats.toString({
            colors: true
        }));
        callback();
    });
});
//打包为GridManagerSite.zip
gulp.task('GridManagerSite', function() {
    console.log('GridManagerSite');
    return gulp.src([buildPath + '/**/*.*'])
        .pipe(zip(zipName))
        .pipe(gulp.dest(''));
});
/**
 * 命令所对应功能:
 * gulp: 构建未压缩的项目
 * gulp develop: 构建未压缩的项目
 * gulp production: 构建压缩的项目, 并生成zip包
 * */

webpack.config.js

/*
* webpack只对js进行控制
* jsx transform js
* es6 transform es5
* 注意:
* html,css 及打包压缩等使用gulp实现
* */
var webpack = require('webpack');
var path = require('path');
var buildPath = 'GridManager';
module.exports = {
    entry: {
        'index': ['./src/app/model.js', './src/app/index.jsx'],
        'about': './src/app/about/index.jsx',
        'api': './src/app/api/index.jsx',
        'demo': ['./src/app/demo/model.js', './src/app/demo/index.jsx'],
        'faq': './src/app/faq/index.jsx',
        'version': './src/app/version/index.jsx',
        'common': ['./src/common/header.jsx', './src/common/footer.jsx', './src/common/tool.js']
    },
    output: {
        path: path.join(__dirname, buildPath),
        filename: '[name].build.js',
        publicPath: '/' + buildPath + ''
    },
    module: {
        loaders: [
            {
                test: /.js?$/,
                loaders: ['babel?{"presets":["es2015"]}'],
                exclude: /(node_modules|bower_components)/,
                include: [path.join(__dirname, 'src')]
            },
            {
                test: /.jsx$/,
                loader: 'babel-loader!jsx-loader?harmony'
            },
            {
                test: /.html$/,
                loader: 'file?name=[path][name]-[hash:20].[ext]',
                exclude: [/(node_modules|bower_components)/],
                include: [path.join(__dirname, 'src/app')]
            }
        ]
    }
};



注意事项

1.在 gulpfile.js 中调用 webpack

gulp.task('webpack:build', function(callback) {
    // webpackConfig 为 webpack.config.js 中的内容
    var myConfig = Object.create(webpackConfig);
    // run webpack
    webpack(myConfig, function(err, stats) {
        if(err) throw new gutil.PluginError('webpack:build', err);
        gulpUtil.log('[webpack:build]', stats.toString({
            colors: true
        }));
        callback();
    });
});


2.存在js的压缩时, 必须在压缩前先执行 webpack 。以保证在执行压缩时, 已经将全部的 jsx 转换为 js

gulp.task('uglify', ['webpack:build'], function(){
    return gulp.src([buildPath + '/**/*'])
        .pipe(gulpIf('*.html', htmlmin(miniHtmlOptions).on('error', gulpUtil.log)))
        .pipe(gulpIf('*.js', uglify().on('error', gulpUtil.log)))
        .pipe(gulpIf('*.css', minifyCss()))
        .pipe(gulp.dest(buildPath));
});