背景
隨著互聯(lián)網(wǎng)技術(shù)的不端推進(jìn),以及業(yè)務(wù)場景的越來越復(fù)雜,前端應(yīng)用場景的越來越多元化筛谚,而且隨著前后端技術(shù)的分離捻脖,可以預(yù)期的是目前的前端技術(shù)走向的趨向?qū)⑹嵌喽思夹g(shù)的統(tǒng)一锐峭,智能搭建,中后臺(tái)思想可婶,這次主要為前端的工程化做一次簡單的介紹沿癞。
前端的全棧領(lǐng)域
在舊時(shí)代的公司里多數(shù)是沒有前端工程師這個(gè)概念的h5作為一個(gè)基礎(chǔ)技能被簡單囊括在了工程師的技術(shù)棧內(nèi)被多數(shù)后端工程師應(yīng)用,類似之前的spring mvc 是基礎(chǔ)技能矛渴,由后端工程師開發(fā)椎扬,到現(xiàn)在隨著前端技術(shù)的不斷進(jìn)步,以及預(yù)編譯語言的出現(xiàn)具温,es6 為 javascript 語言提供了類似 import export? promise await const async? 裝飾器蚕涤。 typescript甚至提供了 interface 以及 類型檢驗(yàn)這種幾乎和java一摸一樣的語法 為前端工程化提供了堅(jiān)實(shí)的基礎(chǔ),所以現(xiàn)在前端應(yīng)用也可以像后端應(yīng)用那樣開發(fā)铣猩,而隨著nodejs技術(shù)的不斷推進(jìn)不論是作為一門后端語言也好揖铜,前端應(yīng)用開發(fā)也好都為前端工程師提供了越來越多的
隨著微服務(wù)以及分布式概念的崛起node 在服用應(yīng)用層已經(jīng)不僅僅可以作為一個(gè)web容器而發(fā)揮作用了,更多的可以作為一個(gè)web中間件層插入到整個(gè)通訊周期內(nèi)部达皿。
包的概念
js 包的概念從最原始的閉包天吓,requirejs 的模塊化,到現(xiàn)在npm包的路程一路演變峦椰,可以說包的概念是一路演變逐漸統(tǒng)一的過程但是一個(gè)js 的包與java 的包由于語言上的差別最終的產(chǎn)出還是完全不同的龄寞,我們通常可以將nodejs 的包们何,一個(gè)包的設(shè)計(jì)根據(jù)中心法則我們可以分為?
entity,boundry,dependency
對(duì)于一個(gè)entity而言他通常代表這個(gè)這個(gè)包內(nèi)的固定屬性萄焦,比如我們定義這個(gè)包的功能是處理賬單交易的,那么對(duì)于這個(gè)包而言賬單就是他所對(duì)應(yīng)的實(shí)體,交易就是他要處理的功能拂封,對(duì)于這個(gè)功能我們要進(jìn)行邊界劃分什么是他應(yīng)該做的茬射,一般而言我們需要對(duì)一個(gè)業(yè)務(wù)進(jìn)行域的劃分,交易可能涉及的有錢冒签,貨在抛,人,和交易規(guī)則萧恕,如果我們講這個(gè)包劃分的只是一個(gè)計(jì)算交易金額的包刚梭,那么結(jié)算,訂單票唆,物流我們就應(yīng)該重新開啟一個(gè)新的包朴读,在此之前我們應(yīng)該先畫一張時(shí)序圖,通過流程來劃分走趋,從一個(gè)實(shí)體到另一個(gè)實(shí)體之間流程變化產(chǎn)生的業(yè)務(wù)邏輯做為劃分衅金,這個(gè)通常需要我們對(duì)操作擬人化來處理,假設(shè)會(huì)到古時(shí)候沒有計(jì)算機(jī)的時(shí)候簿煌,交易的結(jié)算都是流轉(zhuǎn)到各個(gè)人身上去處理的氮唯,現(xiàn)在我們需要的是擬人化。
對(duì)于依賴這個(gè)向來都是管理最混亂姨伟,當(dāng)我們業(yè)務(wù)里的某一塊功能需要我們其他業(yè)務(wù)支撐惩琉,比如算法啊或者組件啊這種,或者第三方業(yè)務(wù)支撐夺荒,一把來說我們內(nèi)部業(yè)務(wù)支撐的放在dependencies內(nèi)部瞒渠,而工程構(gòu)建用的比如eslint,webpack放在我們的devDependencies般堆,通常一個(gè)包內(nèi)部必須有文件在孝,index src 和 lib 通常在前端語言未有部署的情況下我們?cè)趕rc里定義我們的entity,core淮摔,component私沮,util等等,在打包編譯成可以外部在cdn 部署的js文件時(shí)有打包工具生成一個(gè)lib包和橙,一般我們的index只需要通過require語法就可以引用我們的包了仔燕,最終部署到cdn之上的也是我們這種包。
組件化治理
這個(gè)是一個(gè)老生常談的事情的現(xiàn)在我們已經(jīng)有很多mvc框架了魔招,比如使用typescript的ag晰搀,es6的react。但是如何劃分一個(gè)組件事實(shí)并沒有一個(gè)合理的劃分办斑。
第一步:找出重復(fù)的部分
第二步:講一個(gè)過于重的組件的功能僅可能的遷移到另一個(gè)輕組件上
第三步:出去多余的臨時(shí)變量外恕,對(duì)于那些只賦值一次的不要再次賦值
第四步:盡可能的在render少寫if else杆逗,對(duì)于那些使用if else 的盡可能使用語義化的組件替代,通常情況下如果一個(gè)組件里有超過三個(gè)以上的判斷邏輯的化就有必要拆成小組件以便于理解
第五步:不要為了少些幾行代碼而將不同的業(yè)務(wù)邏輯柔和在一起寫鳞疲,對(duì)于同樣結(jié)構(gòu)的組件不同邏輯的給予不同props 小組件罪郊,小組件里只有結(jié)構(gòu)沒有邏輯,對(duì)于不同邏輯的直接兩個(gè)組件
第六步:讀寫分離尚洽,對(duì)于代碼中的計(jì)算部分超過五行以上拆成一個(gè)函數(shù)
感悟
想想就先寫這么多吧悔橄,后面有時(shí)間再完善這篇順便附贈(zèng)一篇eslint贈(zèng)與有緣人
======================= js lint =====================================
{
? "env": {
? ? "browser": true,
? ? "node": true,
? ? "es6": true
? },
? "globals": {},
? "plugins": [
? ? "import"
? ],
? "extends": [],
? "parser": "babel-eslint",
? "parserOptions": {
? ? "ecmaVersion": 6,
? ? "sourceType": "module"
? },
? "rules": {
? ? "array-bracket-spacing": [ "error", "never" ],
? ? "block-spacing": [ "error", "always" ],
? ? "brace-style": [ "error", "1tbs" ],
? ? "comma-spacing": [ "error", { "before": false, "after": true } ],
? ? "comma-style": [ "error", "last" ],
? ? "computed-property-spacing": [ "error", "never" ],
? ? "eol-last": [ "error" ],
? ? "indent": [ "error", 2, { "SwitchCase": 1 } ],
? ? "key-spacing": [ "error", { "beforeColon": false, "afterColon": true } ],
? ? "keyword-spacing": [ "error", { "before": true, "after": true } ],
? ? "linebreak-style": [ "error", "unix" ],
? ? "max-lines": [ "error", 500 ],
? ? "new-cap": [ "error", { "newIsCap": true } ],
? ? "new-parens": [ "error" ],
? ? "newline-after-var": [ "error", "always" ],
? ? "newline-before-return": [ "error" ],
? ? "newline-per-chained-call": [ "error", { "ignoreChainWithDepth": 2 } ],
? ? "no-mixed-spaces-and-tabs": [ "error" ],
? ? "no-multiple-empty-lines": [ "error", { "max": 2, "maxEOF": 1 } ],
? ? "no-spaced-func": [ "error" ],
? ? "no-trailing-spaces": [ "error", { "skipBlankLines": true } ],
? ? "no-underscore-dangle": [ "error" ],
? ? "no-whitespace-before-property": [ "error" ],
? ? "object-curly-spacing": [ "error", "always" ],
? ? "one-var": [ "error", "never" ],
? ? "operator-linebreak": [ "error", "after" ],
? ? "padded-blocks": [ "error", "never" ],
? ? "quote-props": [ "error", "as-needed" ],
? ? "quotes": ["error", "single"],
? ? "semi": [ "error", "never" ],
? ? "semi-spacing": [ "error", { "before": false, "after": true } ],
? ? "space-before-blocks": [ "error", "always" ],
? ? "space-infix-ops": [ "error" ],
? ? "space-unary-ops": [ "error", { "words": true, "nonwords": false } ],
? ? "spaced-comment": ["error", "always"],
? ? "unicode-bom": [ "error", "never" ],
? ? "arrow-body-style": [ "error", "as-needed" ],
? ? "arrow-parens": [ "error", "as-needed" ],
? ? "arrow-spacing": [ "error", { "before": true, "after": true } ],
? ? "constructor-super": [ "error"],
? ? "generator-star-spacing": ["error", { "before": false, "after": true }],
? ? "yield-star-spacing": [ "error", "before" ],
? ? "prefer-template": [ "error" ],
? ? "rest-spread-spacing": [ "error", "never" ],
? ? "template-curly-spacing": [ "error", "never" ],
? ? "comma-dangle": [ "error", "never" ],
? ? "space-before-function-paren": [ "error", "never" ],
? ? "no-var": [ "error" ],
? ? "object-shorthand": [ "error", "always" ],
? ? "no-duplicate-imports": [ "error" ],
? ? "import/export": [ "error" ],
? ? "import/imports-first": [ "error",? "absolute-first" ],
? ? "import/newline-after-import": [ "error" ],
? ? "no-unused-vars": [ "error" ]
? }
}
=============================? ? jsx? ?========================================
{
? "ecmaFeatures": {
? ? "jsx": true
? },
? "parserOptions": {
? ? "ecmaFeatures": {
? ? ? "jsx": true,
? ? ? "experimentalObjectRestSpread": true
? ? }
? },
? "plugins": [
? ? "react"
? ],
? "rules": {
? ? "jsx-quotes": [ "error", "prefer-double" ],
? ? "react/jsx-boolean-value": [ "error", "always" ],
? ? "react/jsx-closing-bracket-location": [ "error", "line-aligned" ],
? ? "react/jsx-curly-spacing": [ "error", "never", { "allowMultiline": true } ],
? ? "react/jsx-indent": [ "error", 2 ],
? ? "react/jsx-indent-props": [ "error", 2 ],
? ? "react/jsx-pascal-case": [ "error" ],
? ? "react/jsx-uses-react": [ "error" ],
? ? "react/jsx-uses-vars": [ "error" ],
? ? "react/prefer-es6-class": [ "error", "always" ],
? ? "react/prefer-stateless-function": [ "error" ],
? ? "react/self-closing-comp": [ "error" ],
? ? "react/jsx-space-before-closing": [ "error", "always" ],
? ? "react/jsx-equals-spacing": [ "error", "never" ],
? ? "react/jsx-wrap-multilines": [ "error" ],
? ? "react/no-multi-comp": [ "error", { "ignoreStateless": true } ],
? ? "react/no-direct-mutation-state": [ "error" ],
? ? "react/jsx-key": [ "error" ],
? ? "react/jsx-no-duplicate-props": [ "error" ],
? ? "react/no-unknown-property": [ "error" ]
? }
}