2.2 Browserify + Gulp + Babelify

优质
小牛编辑
120浏览
2023-12-01

一看就懂的 React 开发环境建置与 Webpack 入门教学

在进入第二种方法前,首先先介绍一下会用到 BrowserifyGulpBabelify 三种前端开发常会用到的工具:

Browserify

  • 如同官网上说明的:Browserify lets you require('modules') in the browser by bundling up all of your dependencies.,Browserify 是一个可以让你在浏览器端也能使用像 Node 用的 CommonJS 规範一样,用输出(export)和引用(require)来管理模组。此外,也能使用许多在 NPM 中的模组

Gulp

  • Gulp 是一个前端任务工具自动化管理工具。随着前端工程的发展(Task Runner),我们在开发前端应用程式时有许多工作是必须重複进行,例如:打包文件、uglify、将 LESS 转译成一般的 CSS 的档案,转译 ES6 语法等工作。若是使用一般手动的方式,往往会造成效率的低下,所以透过像是 Grunt、Gulp 这类的 Task Runner 不但可以提昇效率,也可以更方便管理这些任务。由于 Gulp 是透过 pipeline 方式来处理档案,在使用上比起 Grunt 的方式直观许多,所以这边我们主要讨论的是 Gulp

Babelify

  • Babelify 是一个使用 Browserify 进行 Babel 转换的外挂,你可以想成是一个翻译机,可以将 React 中的 JSXES6 语法转成浏览器相容的 ES5 语法

初步了解了三种工具的概念后,接下来我们就开始我们的环境设置:

  1. 若是电脑中尚未安装 Node(Node.js 是一个开放原始码、跨平台的、可用于伺服器端和网路应用的 Google V8 引擎执行执行环境)和 NPM(Node 套件管理器 Node Package Manager。是一个以 JavaScript 编写的软体套件管理系统,预设环境为 Node.js,从 Node.js 0.6.3 版本开始,npm 被自动附带在安装包中)的话,请先 上官网安装

  2. npm 安装 browserify

  3. npm 安装 gulpgulp-concatgulp-html-replacegulp-streamifygulp-uglifywatchifyvinyl-source-stream 开发环境用的套件(development dependencies)

    1. // 使用 npm install --save-dev 会将安装的套件名称和版本存放到 package.json 的 devDependencies 栏位中
    2. $ npm install --save-dev gulp gulp-concat gulp-html-replace gulp-streamify gulp-uglify watchify vinyl-source-stream
  4. 安装 babelifybabel-preset-es2015babel-preset-react,转译 ES6JSX 开发环境用的套件,并于根目录底下设定 .babelrc,设定转译规则(presets:es2015、react)和使用的外挂

    1. // 使用 npm install --save-dev 会将安装的套件名称和版本存放到 package.json 的 devDependencies 栏位中
    2. $ npm install --save-dev babelify babel-preset-es2015 babel-preset-react
    1. // filename: .babelrc
    2. {
    3. "presets": [
    4. "es2015",
    5. "react",
    6. ],
    7. "plugins": []
    8. }
  5. 安装 react 和 react-dom

    1. $ npm install --save react react-dom
  6. 撰写 Component

  1. // filename: ./app/index.js
  2. import React from 'react';
  3. import ReactDOM from 'react-dom';
  4. class App extends React.Component {
  5. constructor(props) {
  6. super(props);
  7. this.state = {
  8. };
  9. }
  10. render() {
  11. return (
  12. <div>
  13. <h1>Hello, World!</h1>
  14. </div>
  15. );
  16. }
  17. }
  18. ReactDOM.render(<App />, document.getElementById('app'));
  1. <!-- filename: ./index.html -->
  2. <!DOCTYPE html>
  3. <html lang="en">
  4. <head>
  5. <meta charset="UTF-8">
  6. <title>Hello React!</title>
  7. </head>
  8. <body>
  9. <div id="app"></div>
  10. <!-- build:js -->
  11. <script src="./dist/src/bundle.js"></script>
  12. <!-- endbuild -->
  13. </body>
  14. </html>
  1. 设定 gulpfile.js
  1. // filename: gulpfile.js
  2. // 引入所有需要的档案
  3. const gulp = require('gulp');
  4. const uglify = require('gulp-uglify');
  5. const htmlreplace = require('gulp-html-replace');
  6. const source = require('vinyl-source-stream');
  7. const browserify = require('browserify');
  8. const watchify = require('watchify');
  9. const babel = require('babelify');
  10. const streamify = require('gulp-streamify');
  11. // 档案位置参数
  12. const path = {
  13. HTML: 'index.html',
  14. MINIFIED_OUT: 'bundle.min.js',
  15. OUT: 'bundle.js',
  16. DEST: 'dist',
  17. DEST_BUILD: 'dist/build',
  18. DEST_SRC: 'dist/src',
  19. ENTRY_POINT: './app/index.js'
  20. };
  21. // 複製 html 到 dist 资料夹中
  22. gulp.task('copy', function(){
  23. gulp.src(path.HTML)
  24. .pipe(gulp.dest(path.DEST));
  25. });
  26. // 监听档案是否有变化,若有变化则重新编译一次
  27. gulp.task('watch', function() {
  28. gulp.watch(path.HTML, ['copy']);
  29. var watcher = watchify(browserify({
  30. entries: [path.ENTRY_POINT],
  31. transform: [babel],
  32. debug: true,
  33. }));
  34. return watcher.on('update', function () {
  35. watcher.bundle()
  36. .pipe(source(path.OUT))
  37. .pipe(gulp.dest(path.DEST_SRC))
  38. console.log('Updated');
  39. })
  40. .bundle()
  41. .pipe(source(path.OUT))
  42. .pipe(gulp.dest(path.DEST_SRC));
  43. });
  44. // 执行 build production 的流程(包括 uglify、转译等)
  45. gulp.task('copy', function(){
  46. browserify({
  47. entries: [path.ENTRY_POINT],
  48. transform: [babel],
  49. })
  50. .bundle()
  51. .pipe(source(path.MINIFIED_OUT))
  52. .pipe(streamify(uglify(path.MINIFIED_OUT)))
  53. .pipe(gulp.dest(path.DEST_BUILD));
  54. });
  55. // 将 script 引用换成 production 的档案
  56. gulp.task('replaceHTML', function(){
  57. gulp.src(path.HTML)
  58. .pipe(htmlreplace({
  59. 'js': 'build/' + path.MINIFIED_OUT
  60. }))
  61. .pipe(gulp.dest(path.DEST));
  62. });
  63. // 设定 NODE_ENV 为 production
  64. gulp.task('apply-prod-environment', function() {
  65. process.env.NODE_ENV = 'production';
  66. });
  67. // 若直接执行 gulp 会执行 gulp default 的任务:watch、copy。若跑 gulp production,则会执行 build、replaceHTML、apply-prod-environment
  68. gulp.task('production', ['build', 'replaceHTML', 'apply-prod-environment']);
  69. gulp.task('default', ['watch', 'copy']);
  1. 成果展示
    到目前为止我们的资料夹的结构应该会是这样:

一看就懂的 React 开发环境建置与 Webpack 入门教学

接下来我们透过在终端机(terminal)下 gulp 指令来处理我们设定好的任务:

  1. // 当只有输入 gulp 没有输入任务名称时,gulp 会自动执行 default 的任务,我们这边会执行 `watch` 和 `copy` 的任务,前者会监听 `./app/index.js` 是否有改变,有的话则更新。后者则是会把 `index.html` 複製到 `./dist/index.html`
  2. $ gulp

当执行完 gulp 后,我们可以发现多了一个 dist 资料夹

一看就懂的 React 开发环境建置与 Webpack 入门教学

如果我们是要进行 production 的应用程式开发的话,我们可以执行:

// 当输入 gulp production 时,gulp 会执行 production 的任务,我们这边会执行 replaceHTMLbuildapply-prod-environment 的任务,build 任务会进行转译和 uglifyreplaceHTML 会取代 index.html 注解中的 <script> 引入档案,变成引入压缩和 uglify 后的 ./dist/build/bundle.min.jsapply-prod-environment 则是会更改 NODE_ENV 变数,让环境设定改为 production,有兴趣的读者可以参考React 官网说明

  1. $ gulp production

此时我们可以在浏览器上打开我们的 ./dist/hello.html,就可以看到 Hello, world! 了!