使用Gulp和Browserify来搭建React应用程序
2016-05-18 15:43
615 查看
对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中所有
【index.html】
【Child.js】
【Parent.js】
【App.js】
【下载NPM Packages】
【gulpfile.js】
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文件中增加如下:
运行"gulp build"命令,这样,在Tyler/dist/build下多了一个合并压缩后的build.min.js文件。
但这里还有一个问题:Tyler/dist/index.html中依然引用的是src/js中的文件
而我们需要引用的是如下这个文件:
gulp-html-replace就是为解决这个问题而存在。需要两步。
第一步:来到Tyler/src/index.html文件中,添加
第二步:添加task
运行:gulp production
再次来到Tyler/dist/index.html中,惊喜地发现如下:
使用gulp-html-replace生效了!
最后,把完整的gulpfile.js呈现如下:
以上,我们了解了有关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
gulpfule.js
运行gulp命令,在Tyler文件夹下多了dist1文件夹。
【Browserify + Gulp + React(Production Tasks)】
使用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']);
相关文章推荐
- React Native那些事
- reactJS的return里面不要有分号
- [转载]React.js 2016 最佳实践
- React和Redux的连接react-redux
- Reactor模式与Proactor模式
- Reactor模式和Proactor模式
- React学习笔记
- 初识React,Virutal DOM, State以及生命周期
- ReactiveCocoa核心方法bind(绑定)
- ReactNative 使用微软的CodePush进行热更新,继续填坑
- ReactNative浅谈
- React-native windows下android开发入门
- ReactNative 当前url和cookies的获取
- ReactNative 适合初学的第一个教程demo,找租房
- ReactJS读书笔记:DOM操作
- ReactJS学习笔记:感想 - 为什么说Virtual DOM 是React的精髓所在
- ReactJS学习笔记:表单
- ReactJS学习笔记:动画
- ReactNative 从环境和第一个demo说起,填坑教程
- React Native 代码片段