使用gulp+Browserify构建React应用

Posted mqy1023

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用gulp+Browserify构建React应用相关的知识,希望对你有一定的参考价值。

《一》、使用gulp构建React应用

一、React项目结构

.gulpfile.js
./src
    .index.html
    /js
        .App.js
        .Child.js
        .Parent.js

二、代码
index.html 和 js目录下的三个jsx文件如下

//index.html
<!DOCTYPE html>
<html>
<head></head>
<body>
<div id="app"></div>
<script src="../../../react/react.min.js" ></script>
<script src="../../../react-dom/react-dom.min.js" ></script>

<script src="js/Child.js"></script>
<script src="js/Parent.js"></script>
<script src="js/App.js"></script>
</body>
</html>
//Child.js
var Child = React.createClass({
    render: function(){
        return (
            <div>
                and this is the <b>{this.props.name}</b>.
            </div>
        )
    }
});
//Parent.js
var Parent = React.createClass({
    render: function(){
        return (
            <div>
                <div> This is the parent. </div>
                <Child name="child"/>
            </div>
        )
    }
});
//App.js
ReactDOM.render(<Parent />, document.getElementById(‘app‘));

??如上,我们创建了Child和Parent两个组件,Parent组件在App.js中被渲染时,将属性child传给子组件同时渲染子组件
三、gulp在开发和生产两套环境下构建
??1、实现功能
a、开发环境

  • 转换三个jsx文件成js文件并保存在dist/js下
  • 复制index.html到dist目录下
  • 监视jsx和html文件,一有变动执行上面转换和复制任务

b、生产环境

  • 转换jsx成js,并合并然后压缩三个js文件成一个build.min.js保存在dist/build目录下
  • 将html中的<script>标签中三个js替换成上面的build.min.js

??2、下载npm包
a、npm init生成package.json文件— —收集应用中node包信息
b、全局安装gulpnpm install --global gulp
c、其他gulp任务必需的安装node包

npm install --save-dev gulp; 
npm install --save-dev gulp-concat; //合并
npm install --save-dev gulp-uglify; //压缩
npm install --save-dev gulp-react;  //jsx转js
npm install --save-dev gulp-html-replace;//更换.html文件中内容

??3、gulp任务前需准备项
在gulpfile.js顶部,需加入如下,导入用到的node_module模块

var gulp = require(‘gulp‘);
var concat = require(‘gulp-concat‘);
var uglify = require(‘gulp-uglify‘);
var react = require(‘gulp-react‘);
var htmlreplace = require(‘gulp-html-replace‘);

在深入构建不同gulp之前,需创建一个路径项,指定用到的输入文件和输出的文件路径

//指定文件输入和输出路径
var path = {
    HTML: ‘src/index.html‘,
    ALL: [‘src/js/*.js‘, ‘src/js/**/*.js‘, ‘src/index.html‘],
    //【注意】一个个按顺序地指定js,因为默认*.js默认按abc..xyz顺序拼接成build.min.js
    JS: [‘src/js/Child.js‘, ‘src/js/Parent.js‘, ‘src/js/App.js‘], 
    MINIFIED_OUT: ‘build.min.js‘,
    DEST_SRC: ‘dist/js‘,
    DEST_BUILD: ‘dist/build/‘,
    DEST: ‘dist‘
};

??4、开发环境的gulp任务
a、transform转换任务;将jsx转换成js

//jsx转换成js任务
gulp.task(‘transform‘, function(){
    gulp.src(path.JS)
        .pipe(react())
        .pipe(gulp.dest(path.DEST_SRC));
});

b、copy复制任务;将index.html复制到dist目录下

//复制index.html文件
gulp.task(‘copy‘, function(){
    gulp.src(path.HTML)
        .pipe(gulp.dest(path.DEST));
});

c、watch监视任务;

//监视path.ALL下所有文件,一有变动执行transform任务和copy任务
gulp.task(‘watch‘, function(){
    gulp.watch(path.ALL, [‘transform‘, ‘copy‘]);
});

d、默认启动任务

//默认任务;启动监视任务并执行transform和copy任务
gulp.task(‘default‘, [‘watch‘,‘transform‘, ‘copy‘]);

??5、生产环境的gulp任务
a、build任务;该任务将三个js文件按指定顺序(path中的JS)合并成一个文件,然后压缩成build.min.js放在dist/build目录下

gulp.task(‘build‘, function(){
    gulp.src(path.JS)
        .pipe(react())
        .pipe(concat(path.MINIFIED_OUT))
        .pipe(uglify(path.MINIFIED_OUT))
        .pipe(gulp.dest(path.DEST_BUILD));
});

b、更替html中的script任务;替换三个<script>标签成<script src=”build/build.mins.js”>并将index.html文件输入到dist目录

首先需要更替的js需包裹成如下(index.html中)

<!-- build:js -->
<script src="js/Child.js"></script>
<script src="js/Parent.js"></script>
<script src="js/App.js"></script>
<!-- endbuild -->

gulpfile文件中更替任务

gulp.task(‘replaceHTML‘, [‘build‘], function(){
    gulp.src(path.HTML)
        .pipe(htmlreplace({
            ‘js‘: ‘build/‘ + path.MINIFIED_OUT
        }))
        .pipe(gulp.dest(path.DEST));
});

包装启动生产任务

gulp.task(‘production‘, [‘replaceHTML‘]);

源码地址: https://github.com/mqy1023/react-basejs/tree/master/src/demo2



《二》、使用gulp + Browserify构建React应用

1、为什么使用Browserify?
??上面纯gulp实现React应用有一些缺点,会注意到App.js Parent.js Child.js因为加载顺序问题需要小心翼翼添加(如:Child.js必须在Parent.js前加载,因为Parent.js依赖Child.js,同样App.js要在Parent.js加载后);还有当你调试时在jsx中加入debugger,浏览器加载的是jsx转换后的js,所以调试时我们不能定位到原jsx中的具体位置,这对于我们来说很不理想。
2、理解Browserify
??Browserify能帮我们解决上述&其他更多问题。Browserify工具可以让我们类似commonjs模块化加载,即React组件中可以require进其他React组件;模块化改造的js (【注意】module.exports & require & 木有.js后缀)

//Child.js文件
var Child = React.createClass({
    render: function(){
        return (
            <div>
                and this is the <b>{this.props.name}</b>.
            </div>
        )
    }
});
module.exports = Child;
//App.js文件
var Child = require(‘./Child‘);
var Parent = React.createClass({
    render: function(){
        return (
            <div>
                <div> This is the parent. </div>
                <Child name="child"/>
            </div>
        )
    }
});
module.exports = Parent;
//Math.js 
var Parent = require(‘./Parent‘);
ReactDOM.render(<Parent />, document.getElementById(‘app‘));

一、实现功能
a、开发环境

  • 连接起js文件
  • 转换jsx成js
  • 保存在dist目录

b、生产环境

  • 转换jsx成js,并实现合并后压缩,输出到dist目录

二、Browserify + Gulp + React (Development Tasks)开发环境下的tasks
1、卸载gulp-concat

npm uninstall gulp-concat;

2、安装新的NPM包
首先npm install -g browserify全局安装browserify

//others
npm install vinyl-source-stream --save-dev
npm install browserify --save-dev
npm install watchify --save-dev
npm install reactify --save-dev
npm install gulp-streamify --save-dev

【注意】吓尿了。–save-dev要放在后面才行,不明觉厉。。如:npm install --save-dev browserify; //报找不到文件
3、gulpfile导入模块和指定路径

var gulp = require(‘gulp‘);
var uglify = require(‘gulp-uglify‘);
var htmlreplace = require(‘gulp-html-replace‘);
var source = require(‘vinyl-source-stream‘);
var browserify = require(‘browserify‘);
var watchify = require(‘watchify‘);
var reactify = require(‘reactify‘);
var streamify = require(‘gulp-streamify‘);

var path = {
  HTML: ‘src/index.html‘,
  MINIFIED_OUT: ‘build.min.js‘,
  OUT: ‘build.js‘,
  DEST: ‘dist‘,
  DEST_BUILD: ‘dist/build‘,
  DEST_SRC: ‘dist/src‘,
  ENTRY_POINT: ‘./src/js/App.js‘
};

4、copy任务

gulp.task(‘copy‘, function(){
  gulp.src(path.HTML)
    .pipe(gulp.dest(path.DEST));
});

5、watch主任务

gulp.task(‘watch‘, function() {
  gulp.watch(path.HTML, [‘copy‘]);

  var watcher  = watchify(browserify({
    entries: [path.ENTRY_POINT], //入口.js
    transform: [reactify],//jsx转换成js,调试能定位显示原jsx错误具体位置
    debug: true,
    cache: {}, packageCache: {}, fullPaths: true //watchify官网显示此行必须
  }));

  return watcher.on(‘update‘, function () { //更新
    watcher.bundle()
      .pipe(source(path.OUT)) 
      .pipe(gulp.dest(path.DEST_SRC)) 
      console.log(‘Updated‘);
  })
    .bundle() //一执行gulp watch,需要bundle和pipe itself to the dist目录 
    .pipe(source(path.OUT))
    .pipe(gulp.dest(path.DEST_SRC));
});

6、default任务

gulp.task(‘default‘, [‘watch‘]);

三、Browserify + Gulp + React (Production Tasks)生产环境下的tasks
任务都差不多,这里不再赘述

/***************生产版**********
gulp.task(‘build‘,  function(){
    browserify({
        entries: [path.ENTRY_POINT],
        transform: [reactify]
    })
        .bundle()
        .pipe(source(path.MINIFIED_OUT))
        .pipe(streamify(uglify(path.MINIFIED_OUT)))
        .pipe(gulp.dest(path.DEST_BUILD));
});

gulp.task(‘replaceHTML‘, function(){
    gulp.src(path.HTML)
        .pipe(htmlreplace({
            ‘js‘: ‘build/‘ + path.MINIFIED_OUT
        }))
        .pipe(gulp.dest(path.DEST));
});

gulp.task(‘production‘, [‘replaceHTML‘, ‘build‘]);

源码地址: https://github.com/mqy1023/react-basejs/tree/master/src/demo3



参考链接:
http://tylermcginnis.com/reactjs-tutorial-pt-2-building-react-applications-with-gulp-and-browserify/
建议英文可以查看原文,老外的文章就是有很多有用的”废话”;有点遗憾的是,该文章中有些错误,可以老外原文的评论就知道,不知道为什么作者一直没改;本文已针对本人发现的错误做了改正,照着老外原文出错的地方可以回到本文找到解决方案的哈

以上是关于使用gulp+Browserify构建React应用的主要内容,如果未能解决你的问题,请参考以下文章

如何定量分析前端主流的构建工具(Webpack/Rollup/Parcel/Browserify+Gulp)?

browserify 不打包某些文件或者把公共文件提取出来教程

Gulp / Grunt和browserify / webpack之间的关系

gulp 编译es6 react 教程 案例 配置

如何使用 browserify 和 gulp 输出多个包

如何使用 typescript / gulp / browserify 导入 npm 模块