2017年1月19日 星期四

使用webpack打包React.js 專案

在上一篇我們終於在server 上把React.js 跑起來之後,就能繼續寫下去,結果很快的我們就遇到另一個問題,那就是怎麼所有code 都擠在一塊了(yay,
我們上一篇解法的問題,在於我們template render 這個網頁之後,相關的檔案全塞在用<script>引入的javascript 檔案裡,然後這個文件就引不入其他文件了,而React 提倡的模組化該是能把各元件分別歸檔才是。
幸好,我們還是有解法的,利用webpack 讓我們把檔案分開,然後用webpack 打包成單一的 javascript 檔案,據說這種寫法就是<入坑>,因為一用了webpack 就脫不了身,之後都會綁死在webpack 上面。
網路上有些相關的文件,就來一步步跟著做:
https://rhadow.github.io/2015/04/02/webpack-workflow/

首先先準備我們的front-end/main.jsx,因為使用到react跟react-dom,因此在檔案開頭用require 引入,完成的main.jsx 像這樣:
'use strict'

var React = require('react')
var ReactDOM = require('react-dom')

var hello = React.createClass({
  render: function() {
    return (<h2>Hello World!</h2>);
  }
});

ReactDOM.render(
  React.createElement(hello, null),
  document.getElementById('content')
);
接著使用npm 安裝webpack :
npm install --save-dev webpack

並編輯webpack 的設定檔webpack.config.js:
var path = require('path');

var config = {
  entry: [path.resolve(__dirname, './front-end/main.jsx')],
  output: {
    path: path.resolve(__dirname, './static'),
    filename: 'bundle.js'
  },
};

module.exports = config;
這時候使用webpack 來打包,會出現錯誤訊息:
ERROR in ./front-end/main.jsx
Module parse failed: /home/yodalee/website/message-downloader/front-end/main.jsx Unexpected token (8:12)
You may need an appropriate loader to handle this file type.

明顯它看不懂react 的jsx 語法,我們需要設定webpack.config.js 遇到 jsx 檔案就使用babel-loader,還要排除本地的node_modules 裡面的檔案,與output 同層加上:
module: {
  loaders: [{
    test: /\.jsx?$/,
    loader: 'babel-loader',
    exclude: path.join(__dirname, 'node_modules')
  }]
},
並編輯babel的設定檔 .babelrc:
{
  "presets": ["react"],
}
並且使用npm 安裝babel-loader和preset react:
npm install --save-dev babel-loader babel-core babel-preset-react react react-dom

這樣就能用webpack 幫忙打包所有檔案了,有了這個我們就能…嗯…把bower 給刪掉啦(・∀・)。

現在bundle.js 產生在static 裡面,我們可以把template/view.html 清得乾乾淨淨只剩下這樣就會動了:
<!DOCTYPE html>
<html>
  <head lang="en">
    <meta charset="UTF-8">
    <title>View Test</title>
  </head>
  <body>
    <div id="content"></div>
    <script src="/static/bundle.js"></script>
  </body>
</html>
有沒有覺得超級神奇,我也是這麼覺得的。
老實說你要說我一知半解我也認了,前端真的是各種古怪離奇,我看網路上那堆stack overflow的答案怎麼每個都不太一樣,然後試著做不能動的居多(yay,這篇要不是強者我同學人生勝利組一哥冠霖大神的指導,根本要試超久才試得出來。

下面整理一些相關的錯誤訊息:
Unexpected token
well 它看不懂 jsx 的檔案,所以需要用babel-loader 來處理 jsx 檔

Module not found: Error: Cannot resolve module 'react'
表示它在node_modules 裡面找不到require 的module,使用npm 安裝即可

ERROR in ./front-end/main.jsx
Module build failed: Error: Couldn't find preset "react" relative to directory "/home/yodalee/website/message-downloader"
這個是指 babel-loader 沒有相關的……套件?像上面裝了babel-preset-react 就解掉了。

本文感謝強者我同學人生勝利組一哥冠霖大神的指導

2017年1月14日 星期六

使用bower安裝react 前端環境

最近寫message-viewer ,想在bottle.py 執行的server 上面跑React.js,於是就小找了一下,基本上排除了使用 bottle-react 這種懶人套件,我想要的就是能直接寫,同時react jsx 也能在我的管控之下的設定。
後來找到這篇文章,照著它的步驟、跟留言的回覆做就成功了,在這邊整理一下:
https://realpython.com/blog/python/the-ultimate-flask-front-end/

這裡就不介紹React.js 的運作原理了,筆者到目前也還在學,總之我們就跟裡面的一樣,先寫個 view.html,裡面沒什麼,就是用React 寫一個Hello World,直接使用cdnjs 提供的library:https://cdnjs.com/libraries/react/
<!DOCTYPE html>
<html>
  <head lang="en">
    <meta charset="UTF-8">
    <title>View Test</title>
  </head>
  <body>
    <div id="content"></div>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.38/browser.min.js"></script>

    <script type="text/babel">
var hello = React.createClass({
  render: function() {
    return (<h2>Hello World!</h2>);
  }
});

ReactDOM.render(
  React.createElement(hello, null),
  document.getElementById('content')
);
    </script>
  </body>
</html>

接著我們使用任何一種server 的template engine ,我這裡用的是Jinja2就能把網頁跑起來,因為script 來自CDN,所以不必特別設定就能直接使用,打開來應該會出現h1 的Hello World。
app.route('/view', 'GET', MessageViewHandler)
@route('/view')
def MessageViewHandler():
    template = JINJA_ENVIRONMENT.get_template('view.html')
    return template.render()

下一步我們要在自己的電腦上面裝上React,我們使用的是管理前端的管理程式bower,像是bootstrap, React 什麼的都可以裝,

因為我是用archlinux ,本身就提供了bower 套件,所以可以用 pacman 裝bower;非archlinux 的發行版就要用npm 裝bower:
$ npm install -g bower
使用-g 是設定global ,因為在其他project 中八成也會用到bower,但另外,為了服務載了你的project 卻沒有bower 的使用者,我們也需要設定一個npm 的文件:
$ npm init
$ npm install --save-dev bower

有了bower之後,在project 中初始一個bower:
$ bower init
設定直接接受預設設定即可,它會產生一個 bower.json 檔案,我們另外要指定bower 安裝檔案的路徑為static,這要編輯 .bowerrc 並加入下列內容:
{
  "directory": "./static/bower_components"
}
並使用bower 安裝套件,可以用 bower install <package_name> --save 或是在bower.json 中加入套件名之後,再呼叫 bower install;我們這裡用第二種方法,在bower.json 的dependency 下面加上:
"dependencies": {
  "bootstrap": "^3.3.6",
  "react": "^15.1.0",
  "babel": "^5.8.38"
}
並執行 bower install,就能安裝好所需的套件,這時project 中的檔案應該差不多是這樣:
.bowerrc
.gitignore
bower.json
package.json
static/bower_components
template/

現在可以把上面的cdnjs 換成本地資料夾的static link:
<script src="/static/bower_components/react/react.min.js"></script>
<script src="/static/bower_components/react/react-dom.min.js"></script>
<script src="/static/bower_components/babel/browser.min.js"></script>
同時在server 要加上static handler來處理所有對static 的連結:
@route('/static/<path:path>')
def callback(path):
    return static_file(path, root='static')

這樣應該就能在python server 上面寫react.js 的網頁前端了,把剛剛的view.html 打開來跑跑看吧。

2017年1月7日 星期六

多益 900+

去年12/18 ,參加了去年最後一場多益聽讀考試,1/6 公佈成績結果是930,聽力490閱讀440。
之所以要考這場多益,原因是五月退伍後有小小求職過,發現手邊已經沒有適合的英文能力證照,2011 年暑假考的GRE 在今年過期了,當時的成績也不太好,V 60 % / Q 90 % / W 3.5,而且GRE 本身就不是一個廣泛使用的求職英文標準,寫出來大家都不太鳥。
為了及時填補英文能力證明的火力空隙,暑假做了練習題,評估過自己英文實力後,決定報考12/18的多益測驗。

自己的背景當然比較優一點,在學校已經習慣念英文課本跟paper ,聽英文演講也沒有太大問題,口說跟寫作當然…嗯…沒事,就加加減減過得去啦
報考之後下半年就展開練習的生活,大概從8月底持續到12月,除了中間有事出差或太忙,每週末就到圖書館作一回練習題,看看都錯什麼題目。這裡要感謝之前實驗室的地下室長(X 莘予大大借我練習題庫:<New TOEIC 新多益閱讀題庫解析>跟<New TOEIC 新多益聽力題庫解析>,兩本題庫總共2000題,這套據說難度跟真實考試比起來稍難一些,我自己是覺得差不多,全部刷完對我的幫助不小。
另外也有在手機上下載背單字用的App AnkiDroid,單字卡是選用GRE的7500 張單字卡,平時零碎的時間就我把手機拿出來記點單字,我想多少有點幫助(雖然到現在還是沒記完)。
平常練習的時候聽力跟閱讀都是錯10題左右,也就是各450 分,那時候才會定下 >900這個目標,雖然只要超過860就有金色證書,但身為一個整數控,當然是要取個整數900,幸好這次有順利達成目標不用二試。
// 不過我要是有強者我同學:呂神郝神的 -3 dB 大概就 990 了吧QAQ

分科來看,老實說聽力的結果比我想像的好很多,平時練習聽力最怕多益的英、澳口音,跟聽習慣的美、加口音不同,英、澳的口音比較糊成一團,特別聽力 Part 2聽短句問題然後最適當的回答,問題短短的糊成一團就過去了,根本沒聽懂在問什麼,有些 5W1H 的發音還不太一樣,直接聽錯在問什麼;這次測驗事後論壇也有不少人評論有個男生講話特別的糊,好像含著魯蛋在講話,能考到490我也覺得運氣真的很好。
閱讀則是有點偏難(? ,平常練習都可以寫完還剩20分鐘左右,考試可能是太緊張或者太謹慎,剛進到最後一題雙閱讀題,竟然就宣布剩10分鐘,當下有些緊張,最後一題也沒好好讀,成績果然沒有太好看。

小碎念一下,我一直很疑惑多益為什麼不把滿分定在1000 分,拿個990讓人很想進位呀OwO,而且1000 四位數亮出來就是硬比三位數來得有氣勢呀;另外因為身旁實在太多人都990了,害我以為930其實不是個很好的成績 lol不過真要說起來,多益還是比較偏門,像強者我學長丞淵大神在TOEFL 大殺四方,那才是聽說讀寫俱佳的真強者owo。

曾經聽人說過,<這些檢定什麼的都是外顯的,並不能決定你>,仔細想想,要是真有些實際功績,例如在國外念過書或者在外商工作大殺四方,甚或如柏任學長直接在會議會場擔任口譯,丞淵學長在英文辯論場上如戰群雄,他們也許根本不需要這些證書,也能證明自己的英文能力,會考這張證書,也許正是沒有實戰能力的表徵吧?
Anyway,多益順利考過了,評估起來如果再練一兩個月,把閱讀速度跟單字量再提高一些,再考一次閱讀應該能拿到更好的成績,不過目前既然有過900就不打算再考了,接下來就要專心準備七月二戰JLPT N1 了(你看…又是沒實戰能力所以要考證書…QAQ)。