1. 選擇現成的專案模板還是自己搭建專案骨架
搭建一個前端專案的方式有兩種:選擇現成的專案模板、自己搭建專案骨架。
選擇一個現成專案模板是搭建一個專案最快的方式,模板已經把基本的骨架都搭建好了,你只需要向裡面填充具體的業務程式碼,就可以通過內建的工具與命令構建程式碼、部署到伺服器等。
一般來說,一個現成的專案模板會預定義一定的目錄結構、書寫方式,在編寫專案程式碼時需要遵循相應的規範;也會內建必要的工具,比如 .editorconfig、eslint、stylelint、prettier、husky、lint-staged 等;也會內建必要的命令(package.json | scripts
),比如 本地開發:npm run dev
、本地預覽:npm run start
、構建:npm run build
、部署:npm run deploy
等。
社群比較好的專案模板:
- react-boilerplate
- ant-design-pro
- vue-element-admin
- react-starter-kit
- create-react-app
- create-lila-app(我自己用的,哈哈)
這些模板的使用又分為兩種:使用 git
直接克隆到本地、使用命令列建立。
(使用現有模板構建的專案,可以跳過第 2 ~ 7 步)
1.1 使用 git
直接克隆到本地
這是一種真正意義上的模板,可以直接到模板專案的 github
主頁,就能看到整個骨架,比如 react-boilerplate、ant-design-pro、vue-element-admin、react-starter-kit。
以 react-boilerplate
為例:
克隆到本地:
1 |
git clone --depth=1 https://github.com/react-boilerplate/react-boilerplate.git <你的專案名字> |
切換到目錄下:
1 |
cd <span class="hljs-tag"><<span class="hljs-name">你的專案名字</span>></span> |
一般來說,接下來執行 npm run install
安裝專案的依賴後,就可以執行;有些模板可能有內建的初始化命令,比如 react-boilerplate
:
1 |
npm run setup |
啟動應用:
1 |
npm start |
這時,就可以在瀏覽器中預覽應用了。
1.2 使用命令列建立
這種方式需要安裝相應的命令,然後由命令來建立專案。
以 create-react-app
為例:
安裝命令:
1 |
npm install -g create-react-app |
建立專案:
1 |
create-react-app my-app |
執行應用:
1 2 |
cd my-app npm start |
1.3 自己搭建專案骨架
如果你需要定製化,可以選擇自己搭建專案的骨架,但這需要開發者對構建工具如 webpack
、npm
、node
及其生態等有相當的瞭解與應用,才能完美的把控整個專案。
下面將會一步一步的說明如何搭建一個定製化的專案骨架。
2. 選擇合適的規範來寫程式碼
js
模組化的發展大致有這樣一個過程 iife => commonjs/amd => es6
,而在這幾個規範中:
iife
:js
原生支援,但一般不會直接使用這種規範寫程式碼amd
: requirejs 定義的載入規範,但隨著構建工具的出現,便一般不會用這種規範寫程式碼commonjs
:node
的模組載入規範,一般會用這種規範寫node
程式es6
:ECMAScript2015
定義的模組載入規範,需要轉碼後瀏覽器才能執行
這裡推薦使用 es6
的模組化規範來寫程式碼,然後用工具轉換成 es5
的程式碼,並且 es6
的程式碼可以使用 Tree shaking 功能。
參考:
- IIFE(Immediately-invoked function expression)
- Tree shaking
- webpack – tree-shaking
- webpack 如何優雅的使用tree-shaking(搖樹優化)
3. 選擇合適的構建工具
對於前端專案來說,構建工具一般都選用 webpack,webpack
提供了強大的功能和配置化執行。如果你不喜歡複雜的配置,可以嘗試 parcel。
參考:
4. 確定是單頁面應用(SPA)還是多頁面應用
因為單頁面應用與多頁面應用在構建的方式上有很大的不同,所以需要從專案一開始就確定,使用哪種模式來構建專案。
4.1 多頁面應用
傳統多頁面是由後端控制一個 url
對應一個 html
檔案,頁面之間的跳轉需要根據後端給出的 url
跳轉到新的 html
上。比如:
1 2 3 |
http://www.example.com/page1 -> path/to/page1.html http://www.example.com/page2 -> path/to/page2.html http://www.example.com/page3 -> path/to/page3.html |
這種方式的應用,專案裡會有多個入口檔案,搭建專案的時候就需要對這種多入口模式進行封裝。另外,也可以選擇一些封裝的多入口構建工具,如 lila。
4.2 單頁面應用
單頁面應用(single page application),就是隻有一個頁面的應用,頁面的重新整理和內部子頁面的跳轉完全由 js
來控制。
一般單頁面應用都有以下幾個特點:
- 本地路由,由
js
定義路由、根據路由渲染頁面、控制頁面的跳轉 - 所有檔案只會載入一次,最大限度重用檔案,並且極大提升載入速度
- 按需載入,只有真正使用到頁面的時候,才載入相應的檔案
這種方式的應用,專案裡只有一個入口檔案,便無需封裝。
參考:
5. 選擇合適的前端框架與 UI 庫
一般在搭建專案的時候就需要定下前端框架與 UI 庫,因為如果後期想更換前端框架和 UI 庫,代價是很大的。
比較現代化的前端框架:
一些不錯的組合:
- jquery + bootstrap:比較經典的
- react + ant-design、material-ui、Semantic-UI:
react
的組合 - vue + element、iview、vux、mint-ui:
vue
的組合
參考:
6. 定好目錄結構
一個好的目錄結構對一個好的專案而言是非常必要的。
一個好的目錄結構應當具有以下的一些特點:
- 解耦:程式碼儘量去耦合,這樣程式碼邏輯清晰,也容易擴充套件
- 分塊:按照功能對程式碼進行分塊、分組,並能快捷的新增分塊、分組
- 編輯器友好:需要更新功能時,可以很快的定位到相關檔案,並且這些檔案應該是很靠近的,而不至於到處找檔案
比較推薦的目錄結構:
多頁面應用
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 |
|-- src/ 原始碼目錄 |-- page1/ page1 頁面的工作空間(與這個頁面相關的檔案都放在這個目錄下) |-- index.html html 入口檔案 |-- index.js js 入口檔案 |-- index.(css|less|scss) 樣式入口檔案 |-- html/ html 片段目錄 |-- (css|less|scss)/ 樣式檔案目錄 |-- mock/ 本地 json 資料模擬 |-- images/ 圖片檔案目錄 |-- components/ 元件目錄(如果基於 react, vue 等元件化框架) |-- ... |-- sub-dir/ 子目錄 |-- page2/ page2 頁面的工作空間(內部結構參考 page1) |-- ... |-- ... |-- html/ 公共 html 片段 |-- less/ 公共 less 目錄 |-- components/ 公共元件目錄 |-- images/ 公共圖片目錄 |-- mock/ 公共 api-mock 檔案目錄 |-- ... |
單頁面應用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|-- src/ 原始碼目錄 |-- page1/ page1 頁面的工作空間 |-- index.js 入口檔案 |-- services/ service 目錄 |-- models/ model 目錄 |-- mock/ 本地 json 資料模擬 |-- images/ 圖片檔案目錄 |-- components/ 元件目錄(如果基於 react, vue 等元件化框架) |-- ... |-- module1/ 子目錄 |-- page2/ page2 頁面的工作空間(內部結構參考 page1) |-- ... |-- images/ 公共圖片目錄 |-- mock/ 公共 api-mock 檔案目錄 |-- components/ 公共元件目錄 |-- ... |
參考:
7. 搭建一個好的腳手架
搭建一個好的腳手架,能夠更好的編寫程式碼、構建專案等。
可以檢視 搭建自己的前端腳手架 瞭解一些基本的腳手架檔案與工具。
比如:
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 |
|-- / 專案根目錄 |-- src/ 原始碼目錄 |-- package.json npm 專案檔案 |-- README.md 專案說明檔案 |-- CHANGELOG.md 版本更新記錄 |-- .gitignore git 忽略配置檔案 |-- .editorconfig 編輯器配置檔案 |-- .npmrc npm 配置檔案 |-- .npmignore npm 忽略配置檔案 |-- .eslintrc eslint 配置檔案 |-- .eslintignore eslint 忽略配置檔案 |-- .stylelintrc stylelint 配置檔案 |-- .stylelintignore stylelint 忽略配置檔案 |-- .prettierrc prettier 配置檔案 |-- .prettierignore prettier 忽略配置檔案 |-- .babelrc babel 配置檔案 |-- webpack.config.js webpack 配置檔案 |-- rollup.config.js rollup 配置檔案 |-- gulpfile.js gulp 配置檔案 |-- test/ 測試目錄 |-- docs/ 文件目錄 |-- jest.config.js jest 配置檔案 |-- .gitattributes git 屬性配置 |
.editorconfig
: 用這個檔案來統一不同編輯器的一些配置,比如tab
轉 2 個空格、自動插入空尾行、去掉行尾的空格等,http://editorconfig.org- eslint、stylelint、prettier: 規範化程式碼風格、優化程式碼格式等
- husky、lint-staged: 在
git
提交之前對程式碼進行審查,否則不予提交 .gitlab-ci.yml
: gitlab ci 持續整合服務
參考:
=================================================
到這裡為止,一個基本的專案骨架就算搭建好了。
8. 使用版本控制系統管理原始碼(git)
專案搭建好後,需要一個版本控制系統來管理原始碼。
比較常用的版本管理工具有 git、svn,現在一般都用 git
。
一般開源的專案可以託管到 http://github.com,私人的專案可以託管到 https://gitee.com、https://coding.net/,而企業的專案則需要自建版本控制系統了。
自建版本控制系統主要有 gitlab、gogs、gitea:gitlab
是由商業驅動的,比較穩定,社群版是免費的,一般建議選用這個;gogs, gitea
是開源的專案,還不太穩定,期待進一步的更新。
所以,git
+ gitlab
是不錯的配合。
9. 編寫程式碼
編寫程式碼時,js
選用 es6
的模組化規範來寫(如果喜歡用 TypeScript,需要加上 ts-loader),樣式可以用 less、scss、css
來寫。
寫 js
模組檔案時,註釋可以使用 jsdoc 的規範來寫,如果配置相應的工具,可以將這些註釋匯出介面文件。
因為腳手架裡有 husky、lint-staged 的配合,所以每次提交的程式碼都會進行程式碼審查與格式優化,如果不符合規範,則需要把不規範的程式碼進行修改,然後才能提交到程式碼倉庫中。
比如 console.log(haha.hehe);
這段程式碼就會遇到錯誤,不予提交:
這個功能定義在 package.json
中:
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 |
{ "devDependencies": { 工具依賴 "babel-eslint": "^8.2.6", "eslint": "^4.19.1", "husky": "^0.14.3", "lint-staged": "^7.2.0", "prettier": "^1.14.0", "stylelint": "^9.3.0", "eslint-config-airbnb": "^17.0.0", "eslint-config-prettier": "^2.9.0", "eslint-plugin-babel": "^5.1.0", "eslint-plugin-import": "^2.13.0", "eslint-plugin-jsx-a11y": "^6.1.0", "eslint-plugin-prettier": "^2.6.2", "eslint-plugin-react": "^7.10.0", "stylelint-config-prettier": "^3.3.0", "stylelint-config-standard": "^18.2.0" }, "scripts": { 可以新增更多命令 "precommit": "npm run lint-staged", "prettier": "prettier --write "./**/*.{js,jsx,css,less,sass,scss,md,json}"", "eslint": "eslint .", "eslint:fix": "eslint . --fix", "stylelint": "stylelint "./**/*.{css,less,sass,scss}"", "stylelint:fix": "stylelint "./**/*.{css,less,sass,scss}" --fix", "lint-staged": "lint-staged" }, "lint-staged": { 對提交的程式碼進行檢查與矯正 "**/*.{js,jsx}": [ "eslint --fix", "prettier --write", "git add" ], "**/*.{css,less,sass,scss}": [ "stylelint --fix", "prettier --write", "git add" ], "**/*.{md,json}": [ "prettier --write", "git add" ] } } |
- 如果你想禁用這個功能,可以把
scripts
中"precommit"
改成"//precommit"
- 如果你想自定
eslint
檢查程式碼的規範,可以修改.eslintrc, .eslintrc.js
等配置檔案 - 如果你想自定
stylelint
檢查程式碼的規範,可以修改.stylelintrc, .stylelintrc.js
等配置檔案 - 如果你想忽略某些檔案不進行程式碼檢查,可以修改
.eslintignore, .stylelintignore
配置檔案
參考:
10. 元件化
當專案擁有了一定量的程式碼之後,就會發現,有些程式碼是很多頁面共用的,於是把這些程式碼提取出來,封裝成一個元件,供各個地方使用。
當擁有多個專案的時候,有些元件需要跨專案使用,一種方式是複製程式碼到其他專案中,但這種方式會導致元件程式碼很難維護,所以,一般是用另一種方式:元件化。
元件化就是將元件獨立成一個專案,然後在其他專案中安裝這個元件,才能使用。
一般元件化會配合私有 npm 倉庫一起用。
1 2 3 4 5 6 7 8 9 10 11 |
|-- project1/ 專案1 |-- package.json |-- project2/ 專案2 |-- package.json |-- component1/ 元件1 |-- package.json |-- component2/ 元件2 |-- package.json |
在 project1
中安裝 component1, component2
元件:
1 2 3 4 5 6 7 |
# package.json { "dependencies": { "component1": "^0.0.1", "component2": "^0.0.1" } } |
1 2 |
import compoennt1 from 'compoennt1'; import compoennt2 from 'compoennt2'; |
如果想要了解怎樣寫好一個元件(npm package
),可以參考 從 1 到完美,寫一個 js 庫、node 庫、前端元件庫。
參考:
11. 測試
測試的目的在於能以最少的人力和時間發現潛在的各種錯誤和缺陷,這在專案更新、重構等的過程中尤其重要,因為每當更改一些程式碼後,你並不知道這些程式碼有沒有問題、會不會影響其他的模組。如果有了測試,執行一遍測試用例,就知道更改的程式碼有沒有問題、會不會產生影響。
一般前端測試分以下幾種:
- 單元測試:模組單元、函式單元、元件單元等的單元塊的測試
- 整合測試:介面依賴(ajax)、I/O 依賴、環境依賴(localStorage、IndexedDB)等的上下文的整合測試
- 樣式測試:對樣式的測試
- E2E 測試:端到端測試,也就是在實際生產環境測試整個應用
一般會用到下面的一些工具:
另外,可以參考 聊聊前端開發的測試。
12. 構建
一般單頁面應用的構建會有 npm run build
的命令來構建專案,然後會輸出一個 html
檔案,一些 js/css/images ...
檔案,然後把這些檔案部署到伺服器就可以了。
多頁面應用的構建要複雜一些,因為是多入口的,所以一般會封裝構建工具,然後通過引數傳入多個入口:
1 |
npm run build -- page1 page2 dir1/* dir2/all --env test/prod |
page1, page2
確定構建哪些頁面;dir1/*, dir2/all
某個目錄下所有的頁面;all, *
整個專案所有的頁面- 有時候可能還會針對不同的伺服器環境(比如測試機、正式機)做出不同的構建,可以在後面加引數
--
用來分割npm
本身的引數與指令碼引數,參考 npm – run-script 瞭解詳情
多頁面應用會匯出多個 html
檔案,需要注意這些匯出的 html
不要相沖突了。
當然,也可以用一些已經封裝好的工具,如 lila。
13. 部署
在構建好專案之後,就可以部署到伺服器了。
傳統的方式,可以用 ftp, sftp
等工具,手動傳到伺服器,但這種方式比較笨拙,不夠自動化。
自動化的,可以用一些工具部署到伺服器,如 gulp、gulp-ssh,當然也可以用一些封裝的工具,如 md-sync、lila 等
以 md-sync
為例:
1 |
npm install md-sync --save-dev |
md-sync.config.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 |
module.exports = [ { src: './build/**/*', remotePath: 'remotePath', server: { ignoreErrors: true, sshConfig: { host: 'host', username: 'username', password: 'password' } }, }, { src: './build/**/*.html', remotePath: 'remotePath2', server: { ignoreErrors: true, sshConfig: { host: 'host', username: 'username', password: 'password' } }, }, ]; |
在 package.json
的 scripts
配置好命令:
1 2 3 |
"scripts": { "deploy": "md-sync" } |
1 |
npm run deploy |
另外,一般大型專案會使用持續整合 + shell
命令(如 rsync
)部署。
14. 持續整合測試、構建、部署
一般大型工程的的構建與測試都會花很長的時間,在本地做這些事情的話就不太實際,這就需要做持續整合測試、構建、部署了。
持續整合工具用的比較多的:
jenkins
是通用型的工具,可以與 github、bitbucket、gitlab 等程式碼託管服務配合使用,優點是功能強大、外掛多、社群活躍,但缺點是配置複雜、使用難度較高。
gitlab ci
是 gitlab 內部自帶的持續整合功能,優點是使用簡單、配置簡單,但缺點是不及 jenkins
功能強大、繫結 gitlab
才能使用。
以 gitlab
為例(任務定義在 .gitlab-ci.yml
中):
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 |
stages: - install - test - build - deploy # 安裝依賴 install: stage: install only: - dev - master script: - npm install # 執行測試用例 test: stage: test only: - dev - master script: - npm run test # 編譯 build: stage: build only: - dev - master script: - npm run clean - npm run build # 部署伺服器 deploy: stage: deploy only: - dev - master script: - npm run deploy |
以上配置表示只要在 dev
或 master
分支有程式碼推送,就會進行持續整合,依次執行:
npm install
npm run test
npm run clean
npm run build
npm run deploy
最終完成部署。如果中間某個命令失敗了,將停止接下的命令的執行,並將錯誤報告給你。
這些操作都在遠端機器上完成。
=================================================
到這裡為止,基本上完成了一個專案的搭建、編寫、構建。
15. 清理伺服器上過期檔案
現在前端的專案基本上都會用 webpack
打包程式碼,並且檔名(html
檔案除外)都是 hash
化的,如果需要清除過期的檔案而又不想把伺服器上檔案全部刪掉然後重新構建、部署,可以使用 sclean 來清除過期檔案。
16. 收集前端錯誤反饋
當使用者在用線上的程式時,怎麼知道有沒有出 bug;如果出 bug 了,報的是什麼錯;如果是 js 報錯,怎麼知道是那一行執行出了錯?
所以,在程式執行時捕捉 js
指令碼錯誤,並上報到伺服器,是非常有必要的。
這裡就要用到 window.onerror
了:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
window.onerror = (errorMessage, scriptURI, lineNumber, columnNumber, errorObj) => { const data = { title: document.getElementsByTagName('title')[0].innerText, errorMessage, scriptURI, lineNumber, columnNumber, detailMessage: (errorObj && errorObj.message) || '', stack: (errorObj && errorObj.stack) || '', userAgent: window.navigator.userAgent, locationHref: window.location.href, cookie: window.document.cookie, }; post('url', data); // 上報到伺服器 }; |
線上的 js
指令碼都是壓縮過的,需要用 sourcemap
檔案與 source-map 檢視原始的報錯堆疊資訊,可以參考 細說 js 壓縮、sourcemap、通過 sourcemap 查詢原始報錯資訊 瞭解詳細資訊。
參考:
後續
更多部落格,檢視 https://github.com/senntyou/blogs
版權宣告:自由轉載-非商用-非衍生-保持署名(創意共享3.0許可證)