2021年9月4日 星期六

前端工具筆記 - gulp , babel(之二)

 (三) 一個可以實時監察檔案 gulp task


在 gulp 之中,提供了一個 watch() 的 API,watch() 這個 function 會監察符合範圍的檔案,範圍之中的檔案一但更改,就會運行 function 內的內容。透過使用這個 function,我們就可以定下一些實時監察的工作。


打開 gulpfile.js,增加了一個 watch 的 gulp function 讓我們可以監察 src 內的檔案。


const gulp = require("gulp");

const babel = require("gulp-babel");

 

gulp.task("watch", function () {

 

  gulp.watch(['src/*.js'], function(cb) {

    console.log('file changed');

    cb();

  });

 

});

 

gulp.task("default", function () {

 

    gulp.src("src/index.html")

    .pipe(gulp.dest("dist"));

 

    return gulp.src("src/*.js")

    .pipe(babel({

      presets: ["@babel/preset-env"]

    }))

    .pipe(gulp.dest("dist"));

});


這次在 command line 運行 gulp watch,這時 console 應該不會馬上就結束,而是進入了一個等待的狀態。這時我們更改 app.js , 例如把 bob 更改成 alice,然後儲存。


在運行 gulp 的 console 之中應該有以下的信息


PS C:\Sources\gulp-test> gulp watch

[09:29:17] Using gulpfile C:\Sources\gulp-test\gulpfile.js

[09:29:17] Starting 'watch'...

[09:30:51] Starting '<anonymous>'...

file changed

[09:30:51] Finished '<anonymous>' after 9.71 ms


可以看到 watch 之中的內容在更改檔案後成功執行,以上就是 gulp 之中 watch 的作用。


(四) 一個可以實時監察檔案然後更新的 web server


上面提及到 watch 這個 function 的作用,但是要做到更改檔案內容之後自動更新網頁,我們就需要使用到 web server 去 host 我們的檔案。


browser-sync 提供了一個 web server 的功能和可以進行 reload 的 API,使我們可以透過用這個 package 在 gulp 當中達到目的。


首先安裝 browser-sync

npm install browser-sync --save-dev

安裝完之後,把 gulpfile.js 修改成


const gulp = require("gulp");

const babel = require("gulp-babel");

const browserSync = require('browser-sync').create();

 

gulp.task("default", function () {

 

  gulp.src("src/index.html")

  .pipe(gulp.dest("dist"));

 

  return gulp.src("src/*.js")

  .pipe(babel({

    presets: ["@babel/preset-env"]

  }))

  .pipe(gulp.dest("dist"));

});

 

gulp.task('js-watch', gulp.series('default', function (cb) {

  browserSync.reload();

  cb();

}));

 

gulp.task("watch", gulp.series('default', function () {

 

  browserSync.init({

      server: {

          baseDir: "./dist/"

      }

  });

 

  gulp.watch(['src/*.js' , 'src/*.html'], gulp.series('js-watch'));

}));

 

 


首先是在先頭多了一個引用 browser-sync 的變數


const browserSync = require('browser-sync').create();


然後多了一個叫做 js-watch 的 task,在這先前,在這裡使用了一個 gulp.series() 的 API,gulp.series() 可以把輸入的 task 順序運行,在這裡的意思即是會在運行完 default 這個 task 之後再運行後面的 function。


gulp.task('js-watch', gulp.series('default', function (cb) {

  browserSync.reload();

  cb();

}));


然後是 gulp 的 watch task,


gulp.task("watch", gulp.series('default', function () {

 

  browserSync.init({

      server: {

          baseDir: "./dist/"

      }

  });

 

  gulp.watch(['src/*.js' , 'src/*.html'], gulp.series('js-watch'));

}));


一樣這裡用了 gulp.series() ,在一運行 watch 這個 task 的時候就會運行 default 的內容。


browserSync.init 可以建立一個 web server,而這裡的運行目錄則是在 babel 編譯完成後的 dist folder。


而下面的 gulp.watch() function,一但有任何的 js / html 作出改動,就會運行 js-watch 這個 gulp task,會再編譯一次放到 dist folder,然後會自動 refresh 開著的網頁。


接下來測試一下實際的運作,在 command line 打下 gulp watch 之後應該會出現


PS C:\Sources\gulp-test> gulp watch

[09:09:19] Using gulpfile C:\Sources\gulp-test\gulpfile.js

[09:09:19] Starting 'watch'...

[09:09:19] Starting 'default'...

[09:09:20] Finished 'default' after 487 ms

[09:09:20] Starting '<anonymous>'...

[Browsersync] Access URLs:

 ---------------------------------------

       Local: http://localhost:3000

    External: http://___.___.___.___:3000

 ---------------------------------------

          UI: http://localhost:3001

 UI External: http://localhost:3001

 ---------------------------------------

[Browsersync] Serving files from: ./dist/


這些會有一個網頁彈出來,內容正是之前所建立的 index.html


Hello World!

Student Name: alice, Subject: math


這時我們去到 src 入面的 app.js,把 alice 改回 bob 之後儲存。運行 gulp watch 的 command line 會有以下的信息


[09:15:24] Starting 'js-watch'...

[09:15:24] Starting 'default'... 

[09:15:25] Finished 'default' after 87 ms

[09:15:25] Starting '<anonymous>'...

[09:15:25] Finished '<anonymous>' after 1.14 ms

[09:15:25] Finished 'js-watch' after 93 ms

[Browsersync] Reloading Browsers…


打開剛剛彈出來的網頁,發現不用人手 refresh 就已經更新了網站的內容 (因為程式已經自動 reload 了) 。


----


以上就是 gulp 和 babel 的個人學習筆記,只覆蓋了很少的功能,大約是一個入門的用途,想知這這些 package 還可以做到什麼事情的話可以到官方網站研究:


https://babeljs.io/


https://gulpjs.com/


https://browsersync.io/


前端工具筆記 - gulp , babel(之一)

在使用 react 的時候,很多時候在最初配置開發環境的時候,都直接使用 create-react-app 去建立已經自動配置好環境的 project。實在沒有太多的機會去自行配置這些工具,這篇文章就記錄學習這些工具時的一些筆記。


首先先看 gulp,在官方網頁上的描述是 "A toolkit to automate & enhance your workflow",我理解為一個工具可以自動化流程,所做的工作例如會有配合下面會提到的 babel 去 compile js,以及在開發的時候可以觀察檔案有沒有更動,如有的話就再做動作之類等等。


首先跟據這個 Quick Start 的教學 https://gulpjs.com/docs/en/getting-started/quick-start 做到可以在 command line 運行 gulp 進行一個什麼都不做的 task 。


(一)一個可以 copy file 的 gulp task


首先 project 之中創建一個新的資料夾 src,在裡面建立一個新的 index.html, 內容就大約是這樣


<html>

 

<head>

    <title>Index</title>

</head>

 

<body>

    Hello World!

</body>

 

</html>


然後提 gulpfile.js 更改成這樣


const gulp = require("gulp");

 

gulp.task("default", function () {

 

    return gulp.src("src/*")

    .pipe(gulp.dest("dist"));

});


運行 gulp 之後應該會得到以下的結果


PS C:\Sources\gulp-test> gulp

[09:38:17] Using gulpfile C:\Sources\gulp-test\gulpfile.js

[09:38:17] Starting 'default'...

[09:38:17] Finished 'default' after 28 ms


以及會發覺多了一個 dist 的 folder,裡面有的就是剛剛建立的 index.html。


這就是 gulp 的其中一個 API dest() 的使用,當然目前到輸出之間什麼都沒有做,所以看來兩邊輸入輸出都是一模一樣。


(二) 一個可以進行 babel 轉換的 gulp task


Babel 是一個 JavaScript 的編譯器,目的是就算是用新式的 javascript 寫的程式經過編譯後也可以在一些較舊瀏覽器上運行,例如:IE。至於有什麼新式的 javascript 會被轉換,這裡有一個網站 http://es6-features.org/ ,介紹了 es6 種種的增加的功能。


首先要用 npm 安裝 babel。

npm install --save-dev gulp-babel @babel/core


然後把 index.html 更改為這樣


<html>

 

<head>

    <title>Index</title>

</head>

 

<body>

    Hello World!

 

    <div id="container"></div>

 

    <script src="app.js"></script>

</body>

 

</html>

 


見到新增了一個 app.js 的文件,所以我們在同層之中新建一個 app.js ,內容如下:


class student {

    constructor(name, subject){

        this.name = name;

        this.subject = subject;

    }

}

 

let bob = new student("bob","math");

 

document.querySelector("#container").innerHTML = `Student Name: ${bob.name}, Subject: ${bob.subject}`;


在這個時候,如果直接用 chrome 開的話會見到到以下的結果:

Hello World!

Student Name: bob, Subject: math


而使用 IE 11 的話則會只顯示

Hello World!


這時,在 IE 11 按 F12 呼叫 Developer tool 的話,就會發覺 IE 11 有一個 Syntax error 的錯誤,正是 class 這個寫法未支援。


在這個時候回到 gulpfile.js, 更改成以下的模樣,也即時在 Babel 官網後按 Setup 後的 Usage (https://babeljs.io/setup#installation) 再加上一些更改:


const gulp = require("gulp");

const babel = require("gulp-babel");

 

gulp.task("default", function () {

 

    gulp.src("src/index.html")

    .pipe(gulp.dest("dist"));

 

    return gulp.src("src/*.js")

    .pipe(babel({

      presets: ["@babel/preset-env"]

    }))

    .pipe(gulp.dest("dist"));

});


然後再在 command line 運行 gulp,這時在 dist 資料夾之中應該會有 app.js 和 index.html。使用 Chrome 直接開啟 index.html 還是會顯示:


Hello World!

Student Name: bob, Subject: math


再使用 IE11 去開啟 index.html, 就發現 IE11 也能顯示上述的字句了! 


如果在這時打開 dist 的 app.js,就會發現下面的程式碼:


"use strict";

 

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

 

var student = function student(name, subject) {

  _classCallCheck(this, student);

 

  this.name = name;

  this.subject = subject;

};

 

var bob = new student("bob", "math");

document.querySelector("#container").innerHTML = "Student Name: ".concat(bob.name, ", Subject: ").concat(bob.subject);


就是透過 babel 造出這樣的轉換,使到舊式的瀏覽器也能運行最新的代碼。