作業的說明裡面,胡立老師也清楚的說這次作業比較複雜,所以讓我很擔心無法完成作業,結果居然可以即時完成作業,實在太感動了!(當然也是問了胡立老師很多問題才有辦法完成 XD)
稍微研究了學習資源裡的文章,其實都看得霧煞煞,能確定理解的只有安裝而已 XD 所以想說還是先動手安裝,然後再慢慢解決其他問題,不然一直看文章也沒進展。
前幾次作業我有提到對 command line 有莫名的恐懼感,而 Webpack 許多安裝與操作都要用到 command line,所以只好認真惡補一下,除了重新看過之前胡立老師在 Hahow 上的 初心者的計概與 coding 火球術 之外,另外找到 thenewboston 的 youtube 頻道上的 Windows Command Line Tutorials,增進一些基礎。
這次作業套句胡立老師說的「以往是寫 code 難,但作業八難在不是寫 code,所以難」。其實原本 JavaScript 檔案裡的程式碼變動不多,難在 Webpack 安裝跟環境設定,然後利用
require
跟 module.exports
把原本的 script
檔案都打包起來。為什麼要用 Webpack 這種艱難的問題我還沒有能力回答,也是看了好幾篇文章才大略明白,然後中間夾雜更多沒聽過的東西(像是 Gulp、Browserify、CommonJS、AMD、UMD、ReactJS...等等),看得我超混亂。簡單來說就是要讓 JavaScript 模組化,因為還有很多東西都還沒搞懂,所以細節我也解釋不清楚,Preethi Kasireddy 寫的這兩篇講解的蠻詳細的(第二篇只看一半就放棄了 XD):
黃玄寫的 JavaScript 模块化七日谈 也蠻清楚的,只是我看到中間也放棄了 XD
大概了解為什麼要用 Webpack 之後,就開始這次的作業了。Webpack 需要 Node.js 支援,所以要先安裝 Node.js 跟 npm (Node Package Manager),忘記 Node.js 哪一個版本之後就會同時安裝 npm,否則要另外安裝 npm,建議安裝最新版本的 Node.js。
原本想說直接全域(global)安裝 Webpack 到本機之下比較簡單,後來看了 Webpack 官方教學 裡不建議全域安裝,因為會將你鎖定在某一個版本的 Webpack,如果專案採用別的版本就會產生問題。後來把 Webpack 安裝在作業的專案資料夾底下,想要把一開始的全域安裝 Webpack 解除安裝,找到這篇有教學解除全域安裝的項目:Uninstalling Global Packages。
全域安裝:
npm install webpack -g
全域解除安裝:
//check folder npm ls -g --depth=0 //uninstall npm uninstall -g webpack
以上的前置作業以及一些廢話之後,開始來寫作業了。
1. 開啟 cmd.exe 之後,
cd
切換到專案根目錄,然後安裝 Webpack。以下的安裝跟操作都是在專案根目錄下。npm install --save-dev webpack
2. 創建 package.json,用來記錄專案資料,像是專案名稱、版本、作者、套件資訊等等。後面加
-y
可以不用填寫專案資料,之後再編輯也可以。npm init -y
3. 執行 Webpack。如果使用 Mac 或是安裝在全域環境下可以參考官方教學:Webpack Getting Started。
.\node_modules\.bin\webpack --help // for windows user and not installed globally檢查專案資料夾內的 node_modules 資料夾下,如果有 Webpack 資料夾的話表示安裝成功。
4. 安裝 jQuery(參考 npm-jquery),後面加
--save
才會把 jQuery 版本資料新增到 package.json 裡面。npm install jquery --save
5. 安裝 json-loader。
npm install json-loader --save
6. 建立設定檔 webpack.config.js。我先塞一個內容之後才在 Sublime 上編輯。
// creat webpack.config.js with content "test" echo test > webpack.config.js
7. 在 Sublime 新增兩個 json 語言檔、constants.js、i18n.js 跟 utils.js。資料夾跟檔案結構參考胡立老師的這篇:我也想要模組化開發:Webpack。然後在 index.js 中
require
引入 utils.js 跟 constants.js。1) 兩個 json 語言檔:
// lang-zh-tw.json { "title": "用中文直播的頻道" } // lang-en.json { "title": "The Streams in English" }
2) constants.js 檔:
module.exports = { LOCAL_ID: { TITLE: 'title' } }原本不知道為什麼要加這個變數檔案,胡立老師的文章說明是說,json 語言檔案內的
key
是字串,這樣另外用大寫變數儲存 json 語言檔案內的 key
,可以用 constants.Local_ID.TITLE
代表 key
,同時避免在編譯時沒發現打錯字,到執行時才會發現。如果 constants.Local_ID.TITLE
打錯成 constants.Local_ID.TOTLE
,有些幫忙檢查語法的程式就會告訴你找不到這個變數,就可以即使更改,不會到執行才發現出錯。3) i18n.js 檔(把兩個語言檔引入):
module.exports = { "en": require('./i18n/lang-en.json'), "zh-tw": require('./i18n/lang-zh-tw.json') }
4) utils.js 檔:
var i18n = require('./i18n.js'); function getLocalString(id, region) { if(!region || !i18n[region]) { region = 'zh-tw'; } return i18n[region][id]; } module.exports = { getLocalString }參考胡立老師的文章時做作業時,出現了
Uncaught TypeError: Cannot assign to read only property 'exports' of object '#<Object>
錯誤。卡住了一陣子,後來才知道是因為 Webpack 2.2.x 之後的版本不可以將
import
跟 module.exports
放在同一檔案內(參考文章:Webpack@^2.2.x: Uncaught TypeError: Cannot assign to read only property 'exports' of object '#<Object>)。import i18n from './i18n';
改成用 var i18n = require('./i18n.js');
。後來回報給胡立老師,他說當時他是用 Webpack 1,所以是版本不同造成的 bug。5) 在 index.js 中
require
引入 utils.js 跟 constants.js:var utils = require('./utils.js') ; var constants = require('./constants.js') ; ...
修改之前作業用到
window.i18n
的部分:$('.title').text(window.I18N[lang].TITLE);
改成:
$('.title').text(utils.getLocalString(constants.LOCAL_ID.TITLE, lang));
8. 編輯 webpack.config.js 檔:
var webpack = require('webpack'); module.exports = { entry: './src/js/index.js', output: { path: __dirname + '/dist', filename: 'bundle.js' }, module: { loaders: [ { test: /\.json$/, loader: 'json-loader' // npm install json-loader } ] }, plugins: [ new webpack.ProvidePlugin({ $: "jquery", jQuery: "jquery" // npm install jquery }) ] }專案資料夾的架構確定之後,才可以確定
entry
跟 output
的路徑。dist
資料夾是輸出最後的 bundle.js 的地方,等一下執行 Webpack 後自動產生的檔案。這裡也因為參考胡立老師的文章而出現錯誤,目前版本的 Webpack 必須打
loader: 'json-loader'
才可以,文章內是舊版本所以用 loader: 'json'
。還有一點想要特別提出的是,jQuery 我是利用 Webpack plugin 直接在 webpack.config.js 檔裡面定義 jQuery
$
,所以就沒有在 index.js 裡定義 $
(參考 Stackoverflow 文章:Webpack Using Bootstrap jQuery Is Not Defined)。9. 在 HTML 檔案裡,把之前的
script
檔全部取消改成:<script type="text/javascript" src="./dist/bundle.js"></script>
10. 最後只要在 cmd.exe 專案根目錄下執行 Webpack,就會自動把所有的
script
檔都打包成 bundle.js 一個檔案。.\node_modules\.bin\webpack // for windows user and not installed globally
成功的話,在瀏覽器上跑網頁就會如同上一個作業一模一樣,表面上看起來一樣,但後面做了很多手腳 XD
如果之後在任何的
script
檔案(或是 json 檔)裡面有修改,都要再次執行 Webpack(步驟 10),這樣才能更新 bundle.js 的資料。一開始我不知道,所以只在 Sublime 存檔但網頁都沒有變動 XD 要交出作業前,問了胡立老師有點笨的問題(反正我也蠻常問笨問題的 XD),我看其他同學上傳到 GitHub 的作業都沒附上 node_module 那個資料夾,我問為什麼不需要附上那個資料夾?原因是執行 Webpack 之後打包出來的 bundle.js 內已經有專案內需要的所有東西,加上 package.json 那個檔案裡面有每個專案的套件資料,而 node_module 那個資料夾通常很大,所以沒有必要附上 node_module 資料夾到 GitHub 上。
感謝胡立老師每次都耐心回答我的問題,這次也是學習很多,雖然從網頁上根本看不出變化 XD
因為這次作業無法放在 CodePen 上,所以放上我這次作業的 GitHub 跟 GitHub Page。
- hw8 GitHub: https://github.com/pychiang/frontend-intermediate-course/tree/master/answers/hw8
- hw8 GitHub Page: https://pychiang.github.io/frontend-intermediate-course/answers/hw8/index.html
這只是我寫作業過程的筆記,沒有詳細解釋 Webpack 的其他功能,可能也有一些錯誤,如果有錯還請指正。
No comments:
Post a Comment