0%

簡易碼表

透過setInterval()來固定時間加總秒數。計算啟動時間。

參考code: https://codepen.io/dasre/pen/Baodadp

以下只說明重要的code。


Function

Start

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//count 為方便後面停止setInterval使用
count = setInterval(function(){
if(ms === 100){
ms = 0;
if(sec === 60){
sec = 0;
min+=1;
}else{
sec+=1;
}
}else{
ms+=1;
}

let re = pad(min,sec,ms);
document.getElementById('time').innerText = re;
},10);

每10毫秒更新目前的時間。
並做進位動作。
pad()為將<10的數值補為’0X’函式。

stop

clearInterval(count);

時間紀錄

抓取目前的min,sec,ms,傳給pad()輸出目前的分、秒、毫秒,並記錄下來。

reset

將min, sec, ms歸零,重新計時。
並清空時間紀錄。

多Github帳號設定

透過Hostname來決定使用哪一組帳號的SSH Key進行溝通。

SSH生成

首先我們先使用ssh-keygen指令生成金鑰

圖中我們的指令為ssh-keygen -t rsa -C "email@gamil.com"

  • -t 為加密方法的選擇,我們選擇使用RSA加密
  • -C 為註解,會加入SSH的金鑰。可做為金鑰持有者的辨識。

輸入上述指令後,會分別詢問

  • 金鑰存放位置和檔案名稱
  • 是否設置Passphrase(如有輸入,會須重複輸入一次)

上述均輸入完畢後,會產生id_rsa和id_rsa.pub(這邊以預設檔名說明)

  • id_rsa 此為私鑰,也就是要自己保管好的密碼。
  • id_rsa.pub 此為公鑰,也就是對外公開的鑰匙,此會作為與本地端私鑰溝通使用。

將生成的金鑰複製到Github

如果使用linux,可以直接使用ssh-copy-id複製。

mac如要使用ssh-copy-id,需使用Homebrew安裝。

  • mac還可以使用pbcopy來複製,指令pbcopy < ~/.ssh/id_rsa.pub

或是去打開檔案複製都可以。


設定ssh config方便選擇對應的git倉庫

在金鑰該層目錄,新增一config檔案。

可以使用nanovim之類編輯都可以,看個人習慣。

nano ~/.ssh/config

新增下列資訊

1
2
3
4
5
6
7
8
9
Host github.com
HostName github.com
User git
IdentityFile ~/.ssh/id_rsa

Host github-another
HostName github.com
User git
IdentityFile ~/.ssh/id_rsa_new
  • Host 後面的github.com或github-another就是你要連接倉庫的簡稱。
  • HostName 填HostNmae的domain或IP,因為是連github,所以是github.com。
  • User 登入SSH的username,個人習慣統一為git。
  • IdentityFile key的路徑。
    其他還有Port或ForwardX11等指令。不過我們是連github,所以不需要。

設定完成後
可以下ssh -T <Host>檢查。
ex: ssh -T github-another


Clone與push

  • Clone: git clone <host-in-ssh-config>:<username>/<repo>
  • Push: git remote set-url origin <host-in-ssh-config>:<username>/<repo>

補充

以往只有單一一組的github,我們會直接在git的global設定好username和email。

但在有多組的github帳號後,如不想均使用相通的名稱。
需先使用git config — global — unset user.name git config — global — unset user.email取消global設定。

再根據Repo來決定User資料

  • git config user.name "userName"
  • git config user.email "eamil"

Google Apps Script

Google Apps Script(GAS)是什麼,可以參考wiki的介紹。但我一般會把它解釋成一個後端,類似nodejs之類的。

在GAS裡面,你可以透過JavaScript去連接Google的各類服務,或是去連接Google的Firebase資料庫也是可以的。這邊我們會使用GAS來串接Google Sheets。

GAS連結Google表單

要開啟GAS的編輯器,可以從Google表單上方的工具列 工具>指令碼編輯器 或是在 Google雲端硬碟右鍵>更多>Google Apps Script(要先連結GAS應用程式),開啟後副檔名應該會是gs。

目前的GAS是可以使用es6語法的,但因為要做一些對應的設定,這邊我們會使用較舊的JavaScript語法撰寫。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function doPost(e) {
//取得參數
var params = JSON.parse(e.postData.contents);
var num = params.num;
var one = params.one;
var one_other = params.one_other;
var boss_one = params.boss_one;
var to = params.name;
var date = params.date;

//sheet資訊
var SpreadSheet = SpreadsheetApp.openById("");
var Sheet = SpreadSheet.getSheets()[0];


//setValue...
...

return ContentService.createTextOutput(params);
}

上述我們撰寫了一個doPost的function。
doPost其實就是我們在Call這隻gs檔的API,進行post時會觸發的function。

我們可以先透過e這個參數取得post的資料。
接下來透過SpreadsheetApp.openById("")選擇要開啟哪個Google表單的檔案,再透過SpreadSheet.getSheets()[0]綁定好選擇的檔案裡面的哪張表(0表示第一張表)。

選擇好表後,就可以透過getRange()取得表的指定格子位置,並透過setValue()或setFormula()方法來將值存入。

最後的return則是要回傳什麼內容。

GAS部署

在寫完GAS的code後,我們要部署並產生API。
選擇發佈>部署爲網路應用程式,將具有應用程式存取權的使用者改爲 “Anyone, even anonymous“ ,並點選部署。

接下來第一次部署會出現權限核對的一些設定。
基本上就是核對權限>選擇自己的帳戶>進階>前往>允許
點選完畢後會出現下圖

那串URL就是你的API路徑。


補充

  • 在GAS內沒有console.log(),要使用Logger.log()

  • GAS的goGet()和doPost()方法,不能直接return一個object。但可以轉成JSON回傳,詳細可參考



Discord Bot

要製作Discord Bot目前主要有兩個API可以使用。
f

  • discord.io (官方維護)
  • discord.js (民間版本)

但從npm上可以發現目前discord.io已經約兩年沒有更新了,如果遇到任何Bug,要等到官方修復可能需要一定的時間。也因此較推薦使用discord.js這個非官方的套件。


製作方法

  • 先去discord官方建立一個bot(可參考discord.js上的教學)
  • 把bot加入你所要放置的頻道
  • 開始撰寫你的bot
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    // 讀取discord.js套件
    const Discord = require('discord.js');

    // 建立一個Discord client
    const bot = new Discord.Client();

    // 當你要啟動這個bot時,會執行的事情
    bot.on('ready', () => {
    console.log('Ready!');
    });

    // 在建立一個bot時會取得token,這邊要輸入token
    bot.login('your-token');

上述輸入完後,就會在你的Discord頻道看到Discord 機器人。

我這邊因為已經啟動上述的code,所以bot會是線上的狀況,如果沒有執行的話,會顯示離線。

在建立完bot之後,接下來就是要開始監聽輸入的內容。

1
2
3
4
// message裡面會有使用者輸入的內容和使用者資料等等
bot.on('message', message => {
console.log(message.content);
});

我們只需要去監聽使用者輸入的內容做相對應得事情。
例如使用!作為bot要回覆得行為偵測,
接下來就可以使用switch…case的寫法,來判定!後面的內容
如果!後面的內容並不是定義好的
可以再使用default來回覆錯誤訊息。

react-redux

在上一篇redux的文章中,有大致上說明了redux的三個基礎Action、Reducer和Store。這篇文章將說明react如何連結redux。


connect

在上一篇文章中有提到要觸發action,可以透過dispatch來觸發。你要在react用redux提供的dispatch來觸發也沒有問題,但在react-redux中,提供了connect()幫你解決問題。

connect()是一個High Order Component,我們傳入一個component,在經過一些修飾加工,會產生新的component給我們。
詳細HOC的功能這邊不多做說明。

一般我們connect會這樣寫

1
export default connect(mapStateToProps, mapDispatchToProps)(Test)

connect後面的括弧會放mapStateToProps和mapDispatchToProps。

前者就是提供store的資料透過props傳給component,後者則是把dispatch功能提供給component。

最後面Test則是代表我們要傳入的component。


mapStateToProps

1
2
3
4
5
const mapStateToProps = (state) => ({
center: state.center,
zoom: state.zoom,
data: state.data,
});

mapStateToProps裡面可以指定這個component要提供儲存在store的哪些資料。


mapDispatchToProps

1
2
3
4
5
6
7
8
const mapDispatchToProps = dispatch => {
return {
// dispatching plain actions
increment: () => dispatch({ type: 'INCREMENT' }),
decrement: () => dispatch({ type: 'DECREMENT' }),
reset: () => dispatch({ type: 'RESET' })
}
}

mapDispatchToProps 基本上寫法也一樣,return一個object說明,每個key是要做什麼action。

上述的mapDispatchToProps是最基本寫法,如果你的mapDispatchToProps裡面有帶參數的,可以參考官方說明


Provider

Provider也是react-redux內提供的,我們會把他寫在最外層,也就是你要與HTML介接的內個JS中。

1
2
3
4
5
6
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root'),
);

Provider的功用就是要內下層的component可以透過connect取得redux store的資料。


補充

在mapDispatchToProps中,如果沒有要做什麼重新命名或其他行為時,我一般會偷懶直接使用redux action的那個function名稱。

1
2
3
4
export default connect(
mapStateToProps,
{ getTestData, getCoordinates, getNowSelectData },
)(Test);

不過如果你有使用eslint的Airbnb code style,他會要求你寫成mapDispatchToProps就是了。

而假使你這個component中,並沒有要使用到redux store的資料或dispatch行為,可以將內個參數改為null。

1
2
3
4
export default connect(
mapStateToProps,
null,
)(Test);

redux

redux這個名詞,相信有接觸過react的人應該都會聽過。而在網路上,你也可以收尋到許多redux的詳細教學文章,不管是英文的、中文的都有。之所以想寫這篇文章,主要是覺得官方的文件並不能讓人容易將觀念串連起來,而中文的教學雖然也有,但一開始就看到那麼詳細的內容,有時候會越看越模糊。因此想要嘗試用簡單的話語從官方的範例中進行說明,也強化自己的觀念。

在這篇文章中,不會去介紹redux的歷史、以往的技術等等。我們會從直接從react-redux官方範例來進行說明。有些在導入react-redux後不會使用的內容還是會提出來。


redux 三個基礎

Action

主要是用來說明要對目前的資料進行什麼行為。

參考範例 /src/redux/actions.js

1
2
3
4
5
6
7
export const addTodo = content => ({
type: ADD_TODO,
payload: {
id: ++nextTodoId,
content
}
});

這邊抓範例裡面的addTodo來說明。

action又可以分為三個部分

  • Action 指的就是

    1
    2
    3
    4
    5
    6
    7
    {
    type: ADD_TODO,
    payload: {
    id: ++nextTodoId,
    content
    }
    }

    這段,type描述要進行什麼行為,payload則是要帶什麼參數去後面更改資料使用。

  • Action Creator簡單來說就是建立Action的function

    1
    2
    3
    4
    5
    6
    7
    export const addTodo = content => ({
    type: ADD_TODO,
    payload: {
    id: ++nextTodoId,
    content
    }
    });

    上面整段就是一個Action Creator

  • store.dispatch() 觸發一個定義好的行為。但如果是在react中使用redux,通常我們會採用react-redux提供的connect()。
    參考範例 /src/components/AddTodo.js

    1
    2
    3
    4
    export default connect(
    null,
    { addTodo }
    )(AddTodo);

    關於這部分會等到導入react-redux再進行說明。

Reducer

簡單來說就是更新state的地方,會將從action的payload傳進來的參數和目前的state產生一新state。

參考範例 /src/redux/reducers/todo.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
const initialState = {
allIds: [],
byIds: {}
};

export default function(state = initialState, action) {
switch (action.type) {
case ADD_TODO: {
const { id, content } = action.payload;
return {
...state,
allIds: [...state.allIds, id],
byIds: {
...state.byIds,
[id]: {
content,
completed: false
}
}
};
}
case TOGGLE_TODO: {
const { id } = action.payload;
return {
...state,
byIds: {
...state.byIds,
[id]: {
...state.byIds[id],
completed: !state.byIds[id].completed
}
}
};
}
default:
return state;
}
}

initialState初始化state資料。下方透過switch case偵測action type來決定要將state進行怎樣的更新,最後再回傳新state。如果state狀態都沒有要更動,就回傳舊的state。

Reducer幾個重點

  • 永遠不要更改到舊的state資料,而是要產生新的state。所以這邊有用到ES6的object spread。
  • reducer是一個pure function,任何的非同步、call api等行為都不應該在此出現,任何有side effect的行為也是。

Store

串連Action和Reducer使用。

參考範例 /src/redux/store.js

1
2
3
4
import { createStore } from "redux";
import rootReducer from "./reducers";

export default createStore(rootReducer);



  • Redux只會有一個Store。
  • getState()取得state資料。
  • dispatch(action)觸發action事件,更新state。
  • subscribe(listener)監聽事件。

資料流走向

觸發action -> store找到createStore所帶入的reducers,並傳入action和舊的state -> 產生新的state或回傳舊的state,store會再整合成一新單一state。


補充-reducers合併

我們在store部分有提到,redux只會有一個store。但假如我們的reducers拆分成多個檔案時,也就是每個reducers只管跟他有關的東西,我們就可以透過redux的combineReducers將他合併起來,並在建立store時,引入合併好的那個reducers即可。

參考範例 /src/redux/reducers/index.js

1
2
3
4
5
import { combineReducers } from "redux";
import visibilityFilter from "./visibilityFilter";
import todos from "./todos";

export default combineReducers({ todos, visibilityFilter });

關於combineReducers時,也可以給他不同key值,例如寫成

1
2
3
4
{
a: todos,
b: visibilityFilter
}

銜接前面一篇的webpack安裝與簡易配置,這次說明webpack的loader和plugin。

webpack loader

我們前面entry的index.js檔案,有使用到es6的語法,雖然目前市面上的browser大多對es6的語法都可以解析了,但並不是全部都如此,也因此這邊會使用到babel-loader,幫助我們把es6的語法轉成es5。

index.js

原本打包完的檔案內容


安裝方法

1
npm install -D babel-loader @babel/core @babel/preset-env

安裝完後,我們要進webpack.config.js進行設定。在rules的方面,我們可以直接參考github上的使用說明。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
module: {
rules: [
{
test: /\.m?js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
}
]
}

但我個人喜歡寫成這樣

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const babel = {
test: /\.m?js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
}

module: {
rules: [ babel ]
}

這樣寫的好處是可以快速的找到原本定義的內容,且如果當你有不只一個loader要使用時,較不會rules下面有一長串的內容。

我們剛剛安裝babel時,安裝了3個babel的package。

  • babel-loader基本上就是告訴webpack遇到什麼檔案需要使用我這個loader來編譯。
  • @babel/core,babel的核心,使用babel的API。
  • @babel/preset-env,可以根據我們對於瀏覽器的設定,來自動尋找要使用的babel版本。或是直接使用最新版的babel即可。

上述webpack設定內容

  • test是正規表達式,告訴module我們遇到.js的檔案時,要使用下面的設定來編譯。
  • exclude是表示要排除掉哪些檔案,這邊預設已經排除掉node_modules,如果還要排除掉其他的資料夾,如上述的code “|folder”。
  • use裡面的loader是告訴webpack遇到.js檔案要使用哪個loader來進行處理。options就是其他的細部設定,可以設定瀏覽器版本等等,更多詳細可以參考連結

經過babel-loader編譯完成後,內容會變更

原本的const宣告變數方法變成var,箭頭函式變成原本function(){}的寫法。


SCSS to CSS

webpack

以往我們在開發網頁時,基本上就是HTML、CSS和JavaScript三元素。然而在許多的Preprocess框架出現後,開始出現改變。這些的preprocess框架如Sass、Vue等等都是,以Sass為例,他可以有效的幫助我們維護CSS,但瀏覽器本身並不了解Sass,這時候我們就可以透過webpack幫我們把Sass轉譯成CSS。或是說目前常用的ES6語法,也可以透過webpack幫助我們轉譯成browser看得懂的語法。


webpack安裝

要使用webpack之前,請先在專案中產生package.json檔案,可以透過

1
npm init

產生。這邊是使用之前介紹過的express generator產生專案。

接下來就可以安裝webpack了。

1
npm install webpack webpack-cli --save-dev

此時,package.json內應該就會有剛剛安裝的webpack版本資訊。

接下來我們就是要設定webpack的設定檔。


webpack設定

通常一般會在與package.json同一層的目錄下建立一webpack.config.js檔案。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const path = require('path');

module.exports = {
entry: {
'main': './public/javascripts/index.js',
},
output: {
path: path.resolve(__dirname, 'public'),
filename: '[name].bundle.js',
},
module: {

},
plugins: []
}

webpack的設定檔中,大致上有4個屬性可以使用。
其中entry和output是一定要填寫的。

  • entry裡面就是放我們要讀的檔案,如果要讀多個檔案,可以使用object的key-value方式來填寫。這邊的檔案可以使用相對路徑,當然要使用path套件來取得絕對路徑也是可以。
  • output則是檔案經過webpack打包後的存放的路徑和檔名。這邊要使用絕對路徑,所以可以透過path套件來取得目前資料夾的路徑。
    • filename的部分,如果像上述[name]的寫法,name會輸出成entry所輸入key的內容。
    • 通常經過webpack打包完的檔案,我們會使用bundle.js。關於module、chunk、bundle的後續會再說明。
  • loader的部分,在上方的設定檔要寫成module。我個人是把它想成一個處理器的概念(翻意的功能)(負責”讀”的功能)。他可以幫我們把任何東西轉換成JavaScript,讓webpack能看得懂。
  • plugins顧名思義就是外掛的意思。上方的loader部分有提到,loader只會做”讀”的動作,但有時候我們會希望webpack幫我們做一些其他動作(ex:寫)之類的,這時候就需要透過plugins這個欄位。有些webpack的套件需要傳入參數,這時就可以在plugin裡設定。
  • mode為設定專案為production或development。

webpack在package.json設定

在設定完webpack.config.js後,我們要在package.json中的scripts設定webpack啟用的指令。
一般我會設定三個:

  • “build”: “webpack –mode=production”
  • “build:dev”: “webpack –mode=development”
  • “watch”: “webpack –mode=development –watch”

關於mode後面的production和development主要是讓module在打包的時候會選擇使用哪種方式。production通常會讓打包出來的檔案較小,而development主要是要加速開發的速度,也因此在檔案壓縮得部分較小,會盡快把需要編譯的東西編譯完。

watch則是不必每次修改檔案重新使用webpack打包時,需要重新下指令,方便開發時減少指令的輸入。


webpack5 Asset Modules

在webpack5之前,我們知道假使我們要搬移檔案到框架指定的output資料夾,我們要透過file-loader來幫助我們實現。但在webpack5後,webpack將一些我們常用於處理靜態檔案的loader加入webpack中,也就是我們不需要額外去配置這些loader。

目前有配置4種Asset Modules

  • asset/resource 對應的是 file-loader
  • asset/inline 對應的是 url-loader
  • asset/source 對應的是 raw-loader
  • asset則會根據設定(預設是8kb)抉擇檔案會變成inline(像圖片就是轉成base64)還是獨立的檔案。

參考連結


補充:關於NODE_EVN問題

一般來說,我們會設定開發過程中和部署的時候做不同的行為,如抓取不同位置的API、ERROR抱錯的產生等等。我們大多都會使用NODE_ENV來設定。

也因此在package.json中的scripts中,我們可能會設定執行甚麼指令會做什麼環境設定。

在linux和mac中,設定的方式為

1
export NODE_ENV=production

windows為

1
set NODE_ENV=production

也因此如果要跨平台使用,我們可以借用cross-env套件。
安裝方法

1
npm install cross-env --save-dev

而在webpack 4後,我們package.json的scripts設定,--mode production--mode development其實就會幫我們分別設定NODE_ENV=production或development。
但如果還有其他環境的話,還是可以透過cross-env NODE_ENV="env"來進行設定了

express

App.js文件配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
//引入第三方middleware package
//引入http-errors套件
var createError = require('http-errors');

//引入express套件
var express = require('express');

//引入path套件
var path = require('path');

//引入cookie-parser套件
//接收到cookie資料做解析
var cookieParser = require('cookie-parser');

//引入morgan套件
//可以記錄各種事件資料
//例如進行get 或 post等行為
var logger = require('morgan');

//連接透過express.Router()產生實例的router
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');

var app = express();

//模板引擎 這邊使用pug 要使用ejs將pug換成ejs
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');

app.use(logger('dev'));

//可以透過json或一般的字串取得get post等資料
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
//靜態資料 抓到根目錄/public 資料夾
app.use(express.static(path.join(__dirname, 'public')));

//使用上方引入的./routes/index 來管理根目錄router
app.use('/', indexRouter);
//使用上方引入的./routes/user 來管理user router
app.use('/users', usersRouter);

//如果上方的router都沒進入,抓取錯誤
//透過http-errors套件顯示404錯誤
//也可以自定義404錯誤要顯示的title,這邊title定為"This item is not exist!"
//要顯示其他訊息 將404改成其他http狀態碼
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404, 'This item is not exist!'));
});

//錯誤的處理
//預設的處理方式是僅在開發的過程中提供錯誤訊息
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};

// render the error page
res.status(err.status || 500);
res.render('error');
});

module.exports = app;

上述為express App.js的默認設定。

但在實際上,express-generator產生的專案,package.json內npm start實際上是去執行”node ./bin/www”,也就是執行bin資料夾裡www的檔案。下面簡單紀錄www文件配置。


bin/www文件配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#!/usr/bin/env node

/**
* Module dependencies.
*/
//有載入上述說明的app.js檔設定
var app = require('../app');
var debug = require('debug')('expr:server');
var http = require('http');

/**
* Get port from environment and store in Express.
*/
//設定port 如果環境有預設使用環境預設的,沒有就使用3000 port
var port = normalizePort(process.env.PORT || '3000');
app.set('port', port);

/**
* Create HTTP server.
*/

var server = http.createServer(app);

/**
* Listen on provided port, on all network interfaces.
*/

server.listen(port);
server.on('error', onError);
server.on('listening', onListening);

/**
* Normalize a port into a number, string, or false.
*/

function normalizePort(val) {
var port = parseInt(val, 10);

if (isNaN(port)) {
// named pipe
return val;
}

if (port >= 0) {
// port number
return port;
}

return false;
}

/**
* Event listener for HTTP server "error" event.
*/

function onError(error) {
if (error.syscall !== 'listen') {
throw error;
}

var bind = typeof port === 'string'
? 'Pipe ' + port
: 'Port ' + port;

// handle specific listen errors with friendly messages
switch (error.code) {
case 'EACCES':
console.error(bind + ' requires elevated privileges');
process.exit(1);
break;
case 'EADDRINUSE':
console.error(bind + ' is already in use');
process.exit(1);
break;
default:
throw error;
}
}

/**
* Event listener for HTTP server "listening" event.
*/

function onListening() {
var addr = server.address();
var bind = typeof addr === 'string'
? 'pipe ' + addr
: 'port ' + addr.port;
debug('Listening on ' + bind);
}


express router上個人常用的指令

req -> request

res -> response

  • req.params
    • 取得路徑參數值
    • ex
      1
      2
      3
      4
      app.get('user/:number', function(req, res){
      var num = req.params.number;
      res.json({"number": num})
      })
  • res.json()
    • 輸出json資料
  • res.render()
    • 渲染指定畫面
  • res.redirect()
    • 網址重新導向

其餘大致上是邏輯的處理。


補充

  • req.params. …
    • 撈出路由設定的資料
  • req.query. …
    • 取得網址的參數
  • app.use()
    • 使用middleware
    • 類似一層一層的過濾,中間可以處理http的request、response或一些檢查動作等等。
    • 參考

ESLint 安裝與使用

ESLint是一個code的檢查工具,他可以幫我們檢查我們code是否符合我們所設定的規範,並指出在哪裡。而code有著一定的規範,可以讓我們在團隊開發中,有著統一的標準,讓整個團隊開發更一致;對於個人則是可以讓我們學習許多資深開發者的想法,有助於個人程式碼攥寫的提升。


ESLint 安裝

自己較常是全域安裝

1
npm install eslint -g

要注意ESLint對於node和npm版本有要求,如果不符合ESLint所要求的版本,請將node和npm安裝到目前的穩定版本。

一般我會使用

1
npm install npm -g

將npm重新安裝
再透過

1
npm install n -g

安裝n模組
這個n模組其實就是node的版本管理工具


可參考官方介紹&n模組


在中國的SegmentFault也看到一篇不錯的說明,有興趣的可以參考

請注意上述node版本更新不適用windows上,windows上請直接下載最新版的node並進行覆蓋,或參考官方說明文件,如何在windows上安裝多版本node


ESLint建置

在專案中,使用

1
eslint --init

建置.eslintrc.js文件

建置過程中會問一些設定的問題,根據選項去選擇即可。至於style guide部分,有三種規範可以使用。分別是

  • Google
  • Airbnb
  • Standard

其中Airbnb規範最嚴謹,Google次之,個人是選擇Airbnb。關於Airbnb的規範,可參考
連結。目前已經有繁體中文版,上方連結可找到。

在選擇完規範後,會選擇要以yaml、js還是json儲存規範,這邊選擇js。

重開安裝eslint的專案,在問題部分就會提醒你code哪邊不符合規範。

比如說括號前後要空格,或是props參數沒用到等等。

在.eslintrc.js的文件中,會有許多的設定。

  • parser是解析器,可以根據專案設定不同。
  • extends可以設定一些設定好的規範,如前面提到的Airbnb規範,就是寫在extends裡。
  • rules是指額外的規則,像上方圖片裡面有一條提到js文件裡面不能寫JSX,這個問題我們即可在reles加入"react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx"] }],來解決。
  • ecmaFeatures是設定可以使用哪些額外功能,像可以使用JSX等等。
  • plugins使用一些額外的第三方套件。
  • env環境,個人主要在browser和node上。
    關於eslint文件設定方法和參數設定,可參考連結