对React有一定了解之后,我们知道,需要把JSX文件转换成JS文件,组件需要导入导出。本篇就体验使用Gulp把JSX文件转换成JS文件,使用Browserify来把组件捆绑到一个文件并理顺组件之间的依赖关系。

Gulp是用来干嘛的呢?用来把Coffeescript, SASS, JSX等转换成浏览器能理解的JavaScript或CSS,再比如压缩文件到最小尺寸,再比如把文件捆绑到一个文件以减少请求次数,等等。

【文件结构】

node_modules/

gulpfile.js

Typler/

.....src/

..........index.html

..........js/

...............App.js

...............Child.js

...............Parent.js

【需求】

Development阶段:把JSX文件转换成JS文件,并保存到dist/src文件夹中;把src文件夹中的index.html文件复制到dist文件夹中

Product阶段:把所有的JS文件concat, minify, 最终绑定到一个文件build.js,把index.html中所有<script>,替换成一个<script>标签。

【index.html】

<!DOCTYPE html>
<html>
<head></head>
<body>
<div id="app"></div> <script src="../../lib/react.js"></script>
<script src="../../lib/react-dom.js"></script>
<script src="../src/js/Child.js"></script>
<script src="../src/js/Parent.js"></script>
<script src="../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'));

【下载NPM Packages】

npm install --save-dev gulp
npm install --save-dev gulp-concat
npm install --save-dev gulp-uglify
npm install --save-dev gulp-react
npm install --save-dev gulp-html-replace

【gulpfile.js】

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'); var path = {
HTML: 'Tyler/src/index.html',
ALL:['Tyler/src/js/*.js', 'Tyler/src/js/**/*.js','Tyler/src/index.html'],
JS: ['Tyler/src/js/*.js', 'Tyler/src/js/**/*.js'],
MINIFIED_OUT: 'build.min.js',
DEST_SRC: 'Tyler/dist/src', //把从jsx文件转换而来的文件放这里
DEST_BUILD: 'Tyler/dist/build',
DEST: 'Tyler/dist'
}; //获取js的源文件,把jsx转换成js,放到目标文件夹
gulp.task('transform', function(){
gulp.src(path.JS)
.pipe(react())
.pipe(gulp.dest(path.DEST_SRC))
}) //把Tyler/src/index.html这个文件复制放到Tyler/dist中
gulp.task('copy', function(){
gulp.src(path.HTML)
.pipe(gulp.dest(path.DEST));
}); //观察index.html和js文件的变化,执行以上的2个任务
gulp.task('watch', function(){
gulp.watch(path.ALL, ['transform', 'copy']);
}); //名称为default的task,需要
gulp.task('default',['watch','transform', 'copy']);
  • transform这个task用来把jsx转换成js
  • copy这个task用来把Tyler/src/index.html复制拷贝到Tyler/dist/index.html
  • watch这个task用来观察js和html文件的变化,一旦有变化就执行transform和copy这个task
  • default是默认的task,一定需要,执行所有的task

现在执行gulp命令后,Tyler下多了dist文件夹,dist文件夹下多了index.html和src文件夹,src文件夹下有Child.js, Parent.js, App.js.

现在还剩下发布状态下的一些task,要做的事包括:

  • 先获取到所有的js文件
  • 把所有的js文件拼接起来
  • 最小化js文件
  • 把输出文件放到dist/build文件夹中

我们在gulp.js文件中增加如下:

//发布到生产环境的task
gulp.task('build', function () {
gulp.src(path.JS)
.pipe(react())
.pipe(concat(path.MINIFIED_OUT)) //合并到build.min.js文件中
.pipe(uglify(path.MINIFIED_OUT)) //压缩build.min.js文件中
.pipe(gulp.dest(path.DEST_BUILD));//把build.min.js文件放到Tyler/dist/build文件夹中
});

运行"gulp build"命令,这样,在Tyler/dist/build下多了一个合并压缩后的build.min.js文件。

但这里还有一个问题:Tyler/dist/index.html中依然引用的是src/js中的文件

    <script src="../src/js/Child.js"></script>
<script src="../src/js/Parent.js"></script>
<script src="../src/js//App.js"></script>

而我们需要引用的是如下这个文件:

<script src="build/build.min.js"></script>

gulp-html-replace就是为解决这个问题而存在。需要两步。

第一步:来到Tyler/src/index.html文件中,添加<!--build:js--><!--endbuild-->指令。

<!DOCTYPE html>
<html>
<head></head>
<body>
<div id="app"></div> <script src="../../lib/react.js"></script>
<script src="../../lib/react-dom.js"></script>
<!-- build:js -->
<script src="../src/js/Child.js"></script>
<script src="../src/js/Parent.js"></script>
<script src="../src/js//App.js"></script>
<!-- endbuild -->
</body>
</html>

第二步:添加task

//在Tyler/dist/index.html中引用的js文件和Tyler/src/index.html中不一样,需要替换
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']);

运行:gulp production

再次来到Tyler/dist/index.html中,惊喜地发现如下:

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

使用gulp-html-replace生效了!

最后,把完整的gulpfile.js呈现如下:

//Tyler

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'); var path = {
HTML: 'Tyler/src/index.html'
, ALL: ['Tyler/src/js/*.js', 'Tyler/src/js/**/*.js', 'Tyler/src/index.html']
, JS: ['Tyler/src/js/*.js', 'Tyler/src/js/**/*.js']
, MINIFIED_OUT: 'build.min.js'
, DEST_SRC: 'Tyler/dist/src', //把从jsx文件转换而来的文件放这里
DEST_BUILD: 'Tyler/dist/build'
, DEST: 'Tyler/dist'
}; //获取js的源文件,把jsx转换成js,放到目标文件夹
gulp.task('transform', function () {
gulp.src(path.JS)
.pipe(react())
.pipe(gulp.dest(path.DEST_SRC))
}) //把Tyler/src/index.html这个文件复制放到Tyler/dist中
gulp.task('copy', function () {
gulp.src(path.HTML)
.pipe(gulp.dest(path.DEST));
}); //观察index.html和js文件的变化,执行以上的2个任务
gulp.task('watch', function () {
gulp.watch(path.ALL, ['transform', 'copy']);
}); //名称为default的task,需要
gulp.task('default', ['watch', 'transform', 'copy']); //发布到生产环境的task
gulp.task('build', function () {
gulp.src(path.JS)
.pipe(react())
.pipe(concat(path.MINIFIED_OUT)) //合并到build.min.js文件中
.pipe(uglify(path.MINIFIED_OUT)) //压缩build.min.js文件中
.pipe(gulp.dest(path.DEST_BUILD));//把build.min.js文件放到Tyler/dist/build文件夹中
}); //在Tyler/dist/index.html中引用的js文件和Tyler/src/index.html中不一样,需要替换
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']);

以上,我们了解了有关gulp的好多方面,但这样的做法还有那些不足呢?

  • 需要手写各个组件的js文件位置
  • Parent.js依赖Child.js,需要手动让Child.js先与Parent.js加载
  • App.js依赖Parent.js,需要手动让Parent.js先与App.js先加载
  • 很难调试,很难知道jsx哪里出了问题

Browserify就是为了解决以上问题而存在的。

【Browserify+Gulp+React(Developement Tasks)】

安装NPM Packages

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

gulpfule.js

//Tyler using browserify

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: 'Tyler/src/index.html'
, MINIFIED_OUT: 'build.min.js'
, OUT: 'build.js'
, DEST: 'Tyler/dist1'
, DEST_BUILD: 'Tyler/dist1/build'
, DEST_SRC: 'Tyler/dist1/src'
, ENTRY_POINT: 'Tyler/src/js/App.js'
}; //Tyler/src/index.html中复制到TylerTyler/dist中
gulp.task('copy', function () {
gulp.src(path.HTML)
.pipe(gulp.dest(path.DEST));
}); //监测
gulp.task('watch', function () { //监测html文件
gulp.watch(path.HTML, ['copy']); //watchify配合browserify使用,因为单独使用browserify会每次遍历每个组件,一旦有变化就会重新生成绑定文件。而有了watchify,会缓存文件,只更新哪些发生改变的文件
var watcher = watchify(browserify({
entries: [path.ENTRY_POINT],//Tyler/src/js/App.js, browserify会检测Tyler/src/js下的所有js文件,以及Tyler/src/js下所有子文件夹下的js文件
transform: [reactify],//使用reactify把jsx转换成js文件
debug: true,//告诉Browersify使用source maps, souce maps帮助我们在出现错误的时候定位到jsx中的错误行
cache: {},//必须的,browserify告诉我们这样使用
packageCache: {},//必须的,browserify告诉我们这样使用
fullPath: true//必须的,browserify告诉我们这样使用
})); return watcher.on('update', function(){
watcher.bundle()//把所有的jsx文件绑定到一个文件
.pipe(source(path.OUT))
.pipe(gulp.dest(path.DEST_SRC)); console.log('Updated');
})
.bundle()
.pipe(source(path.OUT))
.pipe(gulp.dest(path.DEST_SRC));
}); //默认的task
gulp.task('default', ['watch']);

运行gulp命令,在Tyler文件夹下多了dist1文件夹。

【Browserify + Gulp + React(Production Tasks)】

在发布到生产环境之前,需要添加如下task

//发布到生产环境之前
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']);

使用Browserify完整版如下:

//Tyler using browserify

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: 'Tyler/src/index.html'
, MINIFIED_OUT: 'build.min.js'
, OUT: 'build.js'
, DEST: 'Tyler/dist1'
, DEST_BUILD: 'Tyler/dist1/build'
, DEST_SRC: 'Tyler/dist1/src'
, ENTRY_POINT: 'Tyler/src/js/App.js'
}; //Tyler/src/index.html中复制到TylerTyler/dist中
gulp.task('copy', function () {
gulp.src(path.HTML)
.pipe(gulp.dest(path.DEST));
}); //监测
gulp.task('watch', function () { //监测html文件
gulp.watch(path.HTML, ['copy']); //watchify配合browserify使用,因为单独使用browserify会每次遍历每个组件,一旦有变化就会重新生成绑定文件。而有了watchify,会缓存文件,只更新哪些发生改变的文件
var watcher = watchify(browserify({
entries: [path.ENTRY_POINT], //Tyler/src/js/App.js, browserify会检测Tyler/src/js下的所有js文件,以及Tyler/src/js下所有子文件夹下的js文件
transform: [reactify], //使用reactify把jsx转换成js文件
debug: true, //告诉Browersify使用source maps, souce maps帮助我们在出现错误的时候定位到jsx中的错误行
cache: {}, //必须的,browserify告诉我们这样使用
packageCache: {}, //必须的,browserify告诉我们这样使用
fullPath: true //必须的,browserify告诉我们这样使用
})); return watcher.on('update', function () {
watcher.bundle() //把所有的jsx文件绑定到一个文件
.pipe(source(path.OUT))
.pipe(gulp.dest(path.DEST_SRC)); console.log('Updated');
})
.bundle()
.pipe(source(path.OUT))
.pipe(gulp.dest(path.DEST_SRC)); }); //默认的task
gulp.task('default', ['watch']); //发布到生产环境之前
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']);

使用Gulp和Browserify来搭建React应用程序的更多相关文章

  1. 使用Webpack和Babel来搭建React应用程序

    用Webpack(npm install -g webpack)代码打包,Webpack大致需要知道三件事: 1)让Webpack知道应用程序或js文件的根目录 2)让Webpack知道做何种转换 3 ...

  2. React gulp、Browserify、Webpack实例

    一.gulp var gulp = require('gulp'); var react = require('gulp-react'); gulp.task('jsx', function() { ...

  3. [转载]Sublime Text 3 搭建 React.js 开发环境

    [转载]Sublime Text 3 搭建 React.js 开发环境 Sublime有很强的自定义功能,插件库很庞大,针对新语言插件更新很快,配合使用可以快速搭建适配语言的开发环境. 1. babe ...

  4. sublime text3搭建react native

    Sublime Text 3 搭建React.js开发环境 Sublime有很强的自定义功能,插件库很庞大,针对新语言插件更新很快,配合使用可以快速搭建适配语言的开发环境. 1. babel-subl ...

  5. 前端构建工具的用法—grunt、gulp、browserify、webpack

    随着前端项目的飞速发展,项目越来越大.文件越来越多,前端工程化的工具也越来越多.下面介绍目前最流行的四种构建工具——grunt.gulp.browserify.webpack 所有的构建工具都是基于N ...

  6. 1、在MAC上搭建React Native开发环境

    @import url(http://i.cnblogs.com/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/c ...

  7. react-native —— 在Windows下搭建React Native Android开发环境

    在Windows下搭建React Native Android开发环境 前段时间在开发者头条收藏了 @天地之灵_邓鋆 分享的<在Windows下搭建React Native Android开发环 ...

  8. 手把手教你在Windows下搭建React Native Android开发环境

    最近看到React Native好像好厉害的样子,好奇心驱使之下体验了一下并将在Window下搭建React Natvie Android环境的步骤记录下来,并有需要的朋友参考.(我都是参考官方文档的 ...

  9. 使用Gulp和Browserify创建多个绑定文件

    Browserify是一个Javascript的绑定工具,帮助我们理顺module之间的依赖关系.Gulp用来优化workflow.两者的共同点都是使用流,但在使用流方面也有不同之处: Browser ...

随机推荐

  1. Linux2

    linux开源软件 :apache软件 nginx支持更高的并发访问 MySQL PHP samba mongoDB python 应用领域: 一:服务器  二:嵌入式

  2. ActionScript语言函数重载

    更新:你见过JavaScript支持重载吗,规范就是这么定义的.如果不是研究Java和Flex对象的Serialization,我也不会注意它. 距离写这篇文章已有8年了,时光匆匆啊,今天整理资料时看 ...

  3. [php-src]一个Php扩展的结构

    内容均以php5.6.14为例. 要拥有一个PHP扩展的架子,使用源码中准备好的 /ext/ext_skel 工具,可以生成一个可运行的扩展骨架. 不加选项运行 ./ext_skel,可查看所有可用选 ...

  4. ssh: connect to host gihub.com port 22: Connection timed out

    方案1(本人使用此方案,问题得已解决): 可能是ssh-server未安装或者未启动.我的ubuntu 12.04 默认只安装了openssh-client,并没有安装server. 运行 ps -e ...

  5. 编程之美2014挑战赛 复赛 Codehunt平台试题答案

    var appInsights=window.appInsights||function(config){ function r(config){t[config]=function(){var i= ...

  6. p7 struct and union

    struct  StudentRec           //①声明结构体类型StudentRec{        char StuNum[20];        //②定义结构体的成员变量      ...

  7. 利用扩展事件(Xevents)捕捉高消耗查询

    生产环境中有时需要使用者抓取一些特定的语句分析,如超超长查询,或高IO查询等.一般来说大家对跟踪比较熟悉,主要因为其有完善的UI支持.由于扩展事件在sql2012才提供UI支持,所以虽然在08时就已经 ...

  8. Android 5.x特性概览一

    2014年,Google 携 Android 5.X 重装回归.迄今为止已有已有两年有余,全新设计的 UI风格和更加强悍的性能,再一次奠定了Android 的霸主地位.本文将就 UI 方面 Googl ...

  9. 了解linux下RAID(磁盘阵列)创建和管理

    现在的操作系统,不论是windows 还是linux都具有raid的功能,RAID 分为硬件 RAID 和软件 RAID, 硬件 RAID 是通过 RAID 卡来实现的,软件RAID是通过软件实现的, ...

  10. Arcgis for Javascript 出现“init.js->TypeError: f is not a function”

    环境 采用离线JS包,版本为v3.8 问题描述 在为map添加了 app.map.on("pan-start", this.showHandBeignPan()); 在拖动地图的时 ...