跳到主要內容

使用 Gulp Babel Browserify 打造 React Redux ES6 開發環境 (第二篇)

編譯 SASS 語法 | JavaScript 語法偵錯 | 單元測試

本文目的為介紹以 Gulp 打造 React Redux Router ES6 的開發及產品環境,以下將會說明所需的套件及設定方式,依建制步驟拆成五個篇章,關於 React Redux ES6 Jest 等相關知識不在此篇筆記介紹範圍。

第一篇 - 編譯 ES6 JSX 語法 | CSS JS 自動載入 | 本地端伺服器

  • 編譯 JSX 及 ES6 語法 | Babel Browserify
  • HTML 自動載入 CSS JS | Bower Wiredep Gulp Inject
  • 建立開發用伺服器及自動重新載入 | Gulp Connect

第二篇 - 編譯 SASS | 語法偵錯 | 單元測試

第三篇 - 環境變數 | 程式碼壓縮 | 檔案壓縮 | 輸出隨機檔名

  • 轉換開發及產品環境變數 | Browerify Dotenv Envify
  • JavaScript SASS 程式碼壓縮 | Gulp Sass Uglify
  • 產品環境下打包所有 JS CSS 檔案 | Gulp Useref
  • 輸出的 CSS JS 檔案附加不重複的檔名 | Gulp Rev

第四篇 - 彙整 Gulp task

  • 彙整 Gulp task - development
  • 彙整 Gulp task - production

第五篇 - 導入 Redux React-Router 架構

  • 導入 Redux Router 架構 | React Redux Router

前三篇會依序介紹每個功能及建置方式,第四篇會將零碎的 task 打包成一連串的動作,做成開發及產品環境的指令集,第五篇會把 react-redux 和 react-router 基本架構導入。

基本需求:已安裝 NodeJS 及了解如何使用 npm,並知道如何使用 Gulp 建立 task,第四篇有彙整 Gulp task 的部分,需要理解 NodeJS CommonJS 的模組語法。

編譯 SASS 語法 | Gulp Sass

使用 gulp-sass 能編譯 sass 語法,搭配 gulp-sourcemaps能讓瀏覽器讀取 css 樣式時反映在 .scss 檔案的行數,方便開發除錯。gulp-autoprefixer 套件則能自動加上不同瀏覽器需要的前綴字串。

$ npm install --save-dev gulp-autoprefixer gulp-sass gulp-sourcemaps
// gulpfile.js
var autoprefixer = require('gulp-autoprefixer');
var sass         = require('gulp-sass');
var sourcemaps   = require('gulp-sourcemaps');

// 可以根據不同的開發環境給不同的 option
var sassOptions = {
  'includePaths': ['src/sass/'], 
};
var prefixerOptions = {
  'browsers': ['Last 1 versions']
};

// 加入 sass task
gulp.task('sass', function() {
  return gulp.src('src/sass/style.scss')
    .pipe(sourcemaps.init())
    .pipe(sass(sassOptions).on('error', sass.logError))
    .pipe(sourcemaps.write())
    .pipe(autoprefixer(prefixerOptions))
    .pipe(gulp.dest('dist/css/'));
});

新增 stlyle.scss 在 src/sass 資校夾底下,寫些測試內容接著執行

$ gulp sass
如果在 dist/css 資料夾底下看到 style.css 就是成功編譯了。若已經在第一篇介紹中已經建立了 inject 的 gulp task,可以接著執行
$ gulp inject
把剛剛編譯完的 css 檔案注入至 dist/index.html 之中,如此一來自動注入編譯過的 javascript css 檔案的流程雛形就做出來了。

autoprefixer 設定參數

JavaScript 語法偵錯 | ESLint

Lint 能在開發過程督促自己寫出有意義且依設定格式的程式碼,讓自己養成較好的寫程式習慣,而且能讓團隊開發的程式風格更一致。ESLint 有 plugin 能支援開發 react 環境下的語法提示,我們從安裝 ESLint 這個套件開始:

$ npm install eslint --save-dev
安裝完後輸入,開始設定我們要客製化的提示規則:
$ node_modules/eslint/bin/eslint.js --init

接著會看到類似如此的問答提示:

? How would you like to configure ESLint? (Use arrow keys)
❯ Answer questions about your style
  Use a popular style guide
  Inspect your JavaScript file(s)

若在回答過程中,若需要安裝額外的 plugin 也會自動安裝,回答完成時,在專案的根目錄底下會新增 .eslintrc.js.eslintrc.json 檔案。以下是我建出來的 .eslintrc.js,並做了些微調:

// .eslintrc.js
module.exports = {
  "env": {
    "browser": true,
    "node": true,
    "es6": true,
    "jest": true
  },
  "extends": "eslint:recommended",
  "parserOptions": {
    "ecmaFeatures": {
      "experimentalObjectRestSpread": true,
      "jsx": true
    },
    "sourceType": "module"
  },
  // 需要 eslint-plugin-react node module
  "plugins": [
    "react"
  ],
  "rules": {
    "linebreak-style": [
      "error",
      "unix"
    ],
    "no-console": "off",
    "quotes": [
      "error",
      "single"
    ],
    "semi": [
      "error",
      "always"
    ],
    "react/jsx-uses-react": "error",
    "react/jsx-uses-vars": "error",
    "react/react-in-jsx-scope": "error",
    "react/no-unknown-property": ["off", {"ignore": ["class", "for"]}],
  }
};

若有不想被 ESLint 偵測的資料夾,可以在專案根目錄加入 .eslintignore 檔案,並在其中加入忽略清單,例如:

// .eslintignore
dist/*
public/*
假如自己使用的 IDE 有支援 ESLint 的 plugin,也建議一並裝上搭配使用,可以讓錯誤提示更加及時。

開始建立 Gulp task,先安裝 gulp-eslint

$ npm install --save-dev gulp-eslint
// gulpfile.js
var eslint = require('gulp-eslint');

gulp.task('eslint', function() {
  return gulp.src('src/js/**/*.js')
          .pipe(eslint())
          .pipe(eslint.format())
          .pipe(eslint.failAfterError());
});
執行 task:
$ gulp eslint
就可以得知專案底下的 js 語法有無錯誤。

單元測試 | Jest

使用 Jest 建立 react 專案的單元測試環境,首先安裝相關套件:

$ npm install --save-dev jest babel-jest react-test-renderer  enzyme redux-mock-store
其中 react-test-renderer 用在 Snapshot Testingenzyme 用在 DOM Testingredux-mock-store 用在 Redux 非同步測試的假 store Async Action Creators

接者在 package.json 設定:

// package.json

"scripts": {
  // --coverage 可以在印出測試的覆蓋率表格
  "test": "jest --coverage",
  // $ npm run watch:test 可以監聽測試檔案的變化,自動觸發測試
  "watch:test": "npm test -- --watchAll"
},
// 在 package.json 中新增一個 test 的 property,rootDir 可以指定 jest 要掃描測試的資料夾
"jest": {
  "rootDir": "src/js"
}
--coverage 會統計出測試的覆蓋率,並在專案的根目錄新增一個 coverage 資料夾,將測試的統計結果輸出至其中,記得在 .gitignore 忽略這個資料夾。

Jest 預設會抓取符合正規表示式 (/__tests__/.*|(\\.|/)(test|spec))\\.jsx?$ 的檔案進行測試:

  • __tests__ 資料夾底下的 .js .jsx 檔案
  • 任何檔案名稱後加上 test || spec (例如: Component.test.js 或 Component.spec.js)
想要更改抓取測試檔案的規則可以設定 testRegex 屬性。

新增一個測試用的 Component: MyComponent.js:

// src/js/MyComponent.js
import React from 'react';

export default () => (
  <h1>hello, jest</h1>
);
新增一個測試檔 MyComponent.spec.js
// src/js/MyComponent.spec.js
import MyComponent from './MyComponent';
import React from 'react';
import {shallow} from 'enzyme';

describe('<MyComponent />', function () {
  it('should be defined', () => {
    expect(MyComponent).toBeDefined();
  });

  it('MyComponent's title should be "hello, jest"', function () {
    let myComponent = shallow(<MyComponent />);
    expect(myComponent.find('h1').text()).toEqual('hello, jest');
  });
});
執行測試:
$ npm test
就能看見測試的結果,這個部分不需要多寫 gulp task,而是包裝在 npm test 指令之中,關於如何寫好測試,又是另一個大哉問了,這裡只介紹到環境設定為止。

JEST 的設定文件 Enzyme

留言

這個網誌中的熱門文章

Sublime Text 3 - 建立 React 開發環境

Sublime Text 一直是我很喜歡的前端編輯器,兼具輕量及可攜帶性一直是我很喜歡的特色,然而最近在開發 React 的時候,發現開發沒有特別設定的開發體驗實在不佳,於是在參考許多網路上大大們的文章後完成以下的開發環境需求,下面內容會一步步說明各個需求的設定過程,或許各位有更好的 package 清單,歡迎留言建議。 本篇所建立的開發環境 支援 ES6、JSX 語法高亮 | Support JSX Syntax Highlight 錯誤提示 | ES-Linter Emmet 支援 JSX 語法 | Enable Emmet while writing in JSX 自動完成語法 | React-Snippet 基本需求 Sublime 已經安裝 Package Manager 及 Emmet ,若已使用 SublimeLinter-jshint ,請在使用者設定的地方將他關掉。此外,NodeJS 也需要安裝。 Sublime Package List SublimeLinter SublimeLinter-contrib-eslint Babel Babel Snippets Node Package List eslint babel-eslint 1. 支援 ES6、JSX 語法高亮 使用 package manager 安裝 Babel 、 Babel Snippets ,再次開啟 .js 檔案時,點選 View -> Syntax -> Open all with current extension as... -> Babel -> JavaScript(Babel)。 若遇到想更換主題卻無法切換,可以在 ctrl + ` 的視窗中輸入 view.settings().erase("color_scheme") 。 2. 錯誤提示 npm 安裝 eslint 、 babel-eslint npm install eslint babel-eslint -g 使用 package manager 安裝 SublimeLinter 、 SublimeLinter-contrib-eslint 。 在...

在送出 Ajax 時,將 cooke 值一並送出

在送出 Ajax 時,將 cookie 值一並送出 若 Ajax 送出的網址為相同 domain Ajax 會將瀏覽器的 Cookie 放在 header 的 Cookie 欄位以字串 "key1=value1; key2=value2; key3=value3" 的形式送出 若 Ajax 送出的網址為相不同 domain 預設行為不送 Cooke 這個 header。 若這種情況還是要送 cookie,則需要瀏覽器和伺服器互相配合 瀏覽器: 送 Ajax 時需要加入 withCredentials: true ,以使用 Axios 為例: axios.get('/someCorssOriginUrlIWantToSendCookie', { headers:{ withCredentials: true } }); 伺服器: 回應瀏覽器的 preflight request 時需要特別在 header 注意兩個設定: Access-Control-Allow-Origin 'http://some.domainname' 這種 CORS 情境不能為 *(wildcard),需要指定特定的 domain,且需要和 preflight request 相同。 Access-Control-Allow-Credentials true 註:這邊只針對送出 cookie 時要特別調整的兩個 header 的設定方式,由於 CROS 時,瀏覽器送出 Ajax 的 request 將格式依情況而定。例如 Ajax content-type 為 application/json,伺服器在回應 preflight request 時需要在 header 中加入 Access-Control-Allow-Headers Content-Type,表示伺服器接受這種 content-type 的 request,這部分不在這裡討論。 做完上面的設定,瀏覽器送出 Ajax 時,即會在 header 中加入 Cookie 欄位,值如同同 domain 的形式一樣。 參考網址: MDN