react實(shí)戰(zhàn)(四) nginx生產(chǎn)部署和優(yōu)化

現(xiàn)在項(xiàng)目已經(jīng)有了饼疙,但是要把它放到生產(chǎn)環(huán)境中還是有些事情要做其弊,在這最后一節(jié)衅谷,來(lái)把它們一一搞定椒拗。

這一節(jié)其實(shí)更多是關(guān)于webpack的內(nèi)容。不過(guò)要想把react用得很爽,我們需要一個(gè)現(xiàn)代化的構(gòu)建工具蚀苛。在前面幾節(jié)webpack都在默默地工作著在验。react全都是關(guān)于組件的,組件意味著模塊化堵未,webpack讓前端模塊化得淋漓盡致腋舌。我們的目標(biāo)是要把react用起來(lái),并且是很舒坦的用起來(lái)渗蟹,所以我覺(jué)得這節(jié)并沒(méi)跑題块饺,而且很重要。

打包部署文件

我們的源代碼是沒(méi)法直接跑起來(lái)的雌芽。ES6語(yǔ)法大部分瀏覽器還不完全支持授艰,有些瀏覽器完全不支持。而less世落、sass這些樣式框架就更不用說(shuō)了淮腾。另外對(duì)這些代碼最好進(jìn)行壓縮,以獲得更快的訪問(wèn)速度屉佳。所以在正式發(fā)布這些代碼前必須先要編譯打包谷朝。webpack可是干這個(gè)的以大能手,看名字就知道了忘古。那要怎么打包呢徘禁?

// 終端執(zhí)行:
npm run dist

搞定。
現(xiàn)在我們的項(xiàng)目目錄里多出了一個(gè)名為dist的文件夾髓堪,這里面就是要部署的全部?jī)?nèi)容送朱。由于generator-react-webpack-redux已經(jīng)為我們做好了webpack的一些配置,所以我們看到打包好的文件已經(jīng)經(jīng)過(guò)了壓縮混淆干旁。

服務(wù)器設(shè)置

如果我們?cè)谑褂胷eact-router的時(shí)候選擇了瀏覽器歷史管理方式驶沼,那么服務(wù)器必須要能夠正確處理各種路徑。實(shí)際上我們的應(yīng)用只有一個(gè)頁(yè)面文件争群,在訪問(wèn)各種有效路徑的時(shí)候回怜,服務(wù)都應(yīng)該返回那唯一的頁(yè)面。在開(kāi)發(fā)過(guò)程中换薄,我們通過(guò)npm start指令啟動(dòng)了一個(gè)node服務(wù)玉雾,它已經(jīng)處理好了這些路由。但是在實(shí)際生產(chǎn)環(huán)境中轻要,我們往往會(huì)使用一個(gè)靜態(tài)服務(wù)器复旬,比如nginx或apache。如果把剛才打包好的dist目錄扔給nginx冲泥,你會(huì)發(fā)現(xiàn)只有根路徑可以訪問(wèn)驹碍,通過(guò)點(diǎn)擊跳轉(zhuǎn)到各個(gè)路由沒(méi)問(wèn)題(也就是通過(guò)react-router控制的跳轉(zhuǎn))壁涎,要直接在瀏覽器的地址欄輸入"yourSiteName.com/news"這樣的自路徑就404了。現(xiàn)在以nginx為例來(lái)配置好適合我們應(yīng)用的路由志秃。
我們所需配置的內(nèi)容都在http > server節(jié)點(diǎn)下怔球。
首先考慮對(duì)諸如/news這樣的路徑并不存在對(duì)應(yīng)的頁(yè)面文件,所以對(duì)于未知路徑要都給打發(fā)到根路徑下:

location / { 
      root /Users/someone/my-project/dist; 
      index index.html index.htm; 
      try_files $uri /index.html;
}

這樣浮还,我們?cè)诘刂窓谳斎?yourSiteName.com/news"以后竟坛,nginx沒(méi)有找到news.html,它就嘗試找index.html钧舌,inedex.html打開(kāi)后流码,我們的代碼就生效了,react-router看到地址欄里的路徑是/news延刘,它就會(huì)在一開(kāi)始去匹配/news,并改變狀態(tài)六敬。
至于腳本碘赖、圖片這些靜態(tài)文件我們不用處理,因?yàn)閚ginx按照路徑就可以直接找到這些文件外构。另外就是把后端服務(wù)的接口處理好普泡,nginx代理tomcat這些后端服務(wù)是很常見(jiàn)的配置,只要注意在路徑上服務(wù)和頁(yè)面要能明顯區(qū)分開(kāi)审编,比如所有的后端服務(wù)接口都有.do后綴撼班,這樣配置就行了:

location ~*.do$ { 
     proxy_pass http://192.168.1.1:8088;
}

分離樣式文件

盡管在示例代碼里我把樣式都寫(xiě)成內(nèi)聯(lián)形式的了,但我還是建議寫(xiě)單獨(dú)的樣式文件垒酬。前面也提到過(guò)砰嘁,樣式文件可以直接在js代碼中引入,這對(duì)于構(gòu)造獨(dú)立的模塊非常方便勘究。但是在默認(rèn)狀態(tài)下矮湘,我們會(huì)發(fā)現(xiàn)導(dǎo)出的文件沒(méi)有css文件,實(shí)際上導(dǎo)入的樣式是在代碼運(yùn)行時(shí)加到頁(yè)面上的style標(biāo)簽里的口糕。這樣頁(yè)面渲染性能不太好缅阳,而且會(huì)增大js文件的體積,最好還是把它拿出來(lái)景描。萬(wàn)能的npm里有專干這個(gè)的webpack插件十办,來(lái)把它裝上先:

npm install extract-text-webpack-plugin --save-dev

然后要修改一下webpack的配置文件。由于這個(gè)插件只有在打包的時(shí)候才會(huì)用到超棺,所以我們只改cfg/dist.js文件向族。引入這個(gè)插件,然后在plugins數(shù)組里添加相應(yīng)的項(xiàng)目:

let ExtractTextPlugin = require('extract-text-webpack-plugin');
let config = _.merge({ 
   plugins: [ 
         new ExtractTextPlugin('app.css') 
   ]
});

還要改一下loader说搅。原本loader是寫(xiě)在cfg/base.js里面的炸枣,但是在開(kāi)發(fā)環(huán)境中我們用不到這個(gè)插件,而如果使用了插件提供的loader就會(huì)報(bào)錯(cuò),所以我們?cè)赿ist.js里面把config.module.loaders數(shù)組覆蓋适肠。假如我們的項(xiàng)目里用到了css和less兩種樣式文件霍衫,就在config.module.loaders.push這一段前面添加如下代碼:

config.module.loaders = [
     { 
        test: /\.css$/, 
        loader: ExtractTextPlugin.extract('style-loader', 'css-loader') 
     },
     { 
          test: /\.less/, 
          loader: ExtractTextPlugin.extract('style-loader', 'css-loader!less-loader')
    },
    { 
          test: /\.(png|jpg|gif|woff|woff2)$/,
          loader: 'url-loader?limit=8192'
    }
]

這里除了兩種樣式文件的loader以外,還把base里的一個(gè)非樣式的loader給帶過(guò)來(lái)了侯养,別把它忽略了敦跌,它很有用,一會(huì)兒再說(shuō)逛揩。
現(xiàn)在再運(yùn)行npm run dist柠傍,可以看到asset文件夾里多了一個(gè)app.css文件。別忘了在index.html文件里面引入新生成的樣式文件辩稽。

加載圖片

webpack讓我們可以在js代碼中引入圖片并使用惧笛,引入圖片只需一個(gè)簡(jiǎn)單的require語(yǔ)句:

let logo = require('../images/logo.png');

然后可以像使用其它變量一樣來(lái)使用這個(gè)圖片:

render(){ 
      return <img src={logo}>
}

你可能覺(jué)得,一個(gè)圖片直接用它的路徑就行了逞泄,何必要裝模作樣的引入呢患整?我認(rèn)為有這么做兩個(gè)好處:
首先還是模塊化。如果一個(gè)組件需要用到圖片喷众,在這個(gè)組件文件內(nèi)引入圖片各谚,圖片會(huì)在run dist時(shí)一并打包,不用擔(dān)心圖片丟失到千。
其次很多服務(wù)器會(huì)對(duì)圖片進(jìn)行CDN緩存昌渤,如果你替換了一張圖片,很可能它在一段時(shí)間內(nèi)不會(huì)生效憔四,而通過(guò)webpack引入的圖片是一內(nèi)聯(lián)base64或者重命名為唯一hash文件名的形式打包的膀息,這樣就不會(huì)出現(xiàn)惱人的緩存情況。
不只是在js中引入圖片會(huì)被webpack處理了赵,css里的圖片也會(huì)被同樣的方式處理履婉。
如果你已經(jīng)在你的項(xiàng)目里加上了幾個(gè)小圖片,你可能會(huì)發(fā)現(xiàn)打包后并沒(méi)有看到圖片或者圖片比原來(lái)少斟览,這是因?yàn)橛幸粋€(gè)臨界值毁腿,低于它的圖片會(huì)直接轉(zhuǎn)成base64寫(xiě)在導(dǎo)出的js文件里。這樣也好也不好苛茂,好處是圖片在一開(kāi)始就被載入已烤,后面不會(huì)出現(xiàn)圖片延后載入的效果,用戶體驗(yàn)很好妓羊,不好就是base64比原圖片大小更大胯究,如果圖片比較多,導(dǎo)出的js文件就會(huì)太大躁绸,讓用戶初始等待時(shí)間過(guò)長(zhǎng)裕循。所以我們要權(quán)衡利弊設(shè)置一個(gè)合適的臨界值臣嚣。前面我們?cè)赿ist.js配置文件中重寫(xiě)loaders的時(shí)候把base里的一個(gè)loader帶了過(guò)來(lái),它就是干這個(gè)用的剥哑,test屬性的正則表達(dá)式表明我們想讓webpack處理什么格式的圖片硅则,loader屬性最后的數(shù)字就是內(nèi)聯(lián)圖片臨界值,單位是字節(jié)株婴。我們把它設(shè)置成1K吧:

{ 
      test: /\.(png|jpg|gif|woff|woff2)$/, 
      loader: 'url-loader?limit=1024'
}

多個(gè)入口

我們的目標(biāo)是單頁(yè)應(yīng)用怎虫,但是當(dāng)項(xiàng)目規(guī)模比較大的時(shí)候整個(gè)項(xiàng)目可能會(huì)被拆分成多個(gè)單頁(yè)應(yīng)用。拆分多個(gè)應(yīng)用的關(guān)鍵在于要有多個(gè)入口文件困介。目前我們的項(xiàng)目只有一個(gè)入口文件:src/index.js大审。來(lái)看cfg/dist.js文件,里面的config對(duì)象中entry屬性的值現(xiàn)在是一個(gè)index.js路徑字符串座哩。entry的值也可以是一個(gè)對(duì)象徒扶,這樣就可以聲明多個(gè)入口文件,對(duì)象的key對(duì)應(yīng)著文件名根穷。比如我們想要增加一個(gè)入口文件src/test.js酷愧,先搞點(diǎn)很簡(jiǎn)單的內(nèi)容:

import React from 'react';
import { render } from 'react-dom';
render( 
        <div>TEST</div>, 
        document.getElementById('app')
);

把cfg/dist.js中的config.entry改成這樣:

entry: { 
    app: path.join(__dirname, '../src/index'), 
    test: path.join(__dirname, '../src/test')
}

現(xiàn)在明確指定了兩個(gè)入口文件,然后還要修改config.output.filename:

config.output.filename = '[name].js'

輸出文件時(shí)缠诅,name會(huì)自動(dòng)對(duì)應(yīng)成entry中的key。執(zhí)行npm run dist乍迄,現(xiàn)在asset目錄中多出了個(gè)test.js管引。
使用這個(gè)文件需要另一個(gè)單獨(dú)的頁(yè)面,如果我們用靜態(tài)html頁(yè)面的話闯两,要把頁(yè)面路徑添加到項(xiàng)目根目錄下的package.json中褥伴,在scripts對(duì)象中有個(gè)copy屬性,加到里面就行了漾狼,這樣才能在run dist的時(shí)候把它一并拷貝到dist目錄里重慢。
最后,也許你還要修改一下nginx配置逊躁,讓test路徑單獨(dú)匹配似踱。

分離第三方庫(kù)

你可能發(fā)現(xiàn)了剛才我們把文件分成多個(gè)入口時(shí),新入口文件即使內(nèi)容非常少稽煤,哪怕只渲染了一個(gè)div核芽,生成的文件大小還有上百k。里面其實(shí)主要都是第三方庫(kù)酵熙。這太不優(yōu)雅了轧简,既然這些第三方庫(kù)幾乎會(huì)被所有的應(yīng)用重復(fù)使用,一定得把他們單拎出來(lái)匾二。于是我們需要一個(gè)插件:CommonsChunkPlugin哮独。這個(gè)插件不用單獨(dú)安裝了拳芙,它被包含在webpact.optimize里面。我們打算再輸出一個(gè)叫commons.js的文件皮璧,包含全部第三方庫(kù)舟扎。在cfg/dist.js的plugins數(shù)組里面添加這個(gè)插件:

new webpack.optimize.CommonsChunkPlugin('commons', 'commons.js')

然后在entry對(duì)象里面再添加一個(gè)commons屬性,它的值是一個(gè)數(shù)組恶导,包含所有我們想要拎出來(lái)的庫(kù):

entry: { 
    app: path.join(__dirname, '../src/index'), 
    test: path.join(__dirname, '../src/test'), 
    commons: [ 
        'react', 
        'react-dom', 
        'react-redux', 
        'react-router', 
        'redux', 
        'redux-thunk' 
    ]
}

OK浆竭,輸出的文件多了個(gè)commons.js,而app.js和test.js比原來(lái)小了很多惨寿。這回優(yōu)雅了邦泄。別忘了在所有的頁(yè)面里都把commons.js引進(jìn)去。

按需加載

當(dāng)項(xiàng)目非常大的時(shí)候裂垦,拆分多個(gè)入口文件是一種方案顺囊,還有一種方案是按需加載,也就是懶加載或異步加載蕉拢。我們可以讓用戶真正進(jìn)入一個(gè)路由時(shí)才把對(duì)應(yīng)的組件加載進(jìn)來(lái)特碳,要實(shí)現(xiàn)這個(gè)非常簡(jiǎn)單,只需要一個(gè)webpack的loader:react-router-loader晕换,先用npm把它安裝上午乓,然后修改src/routs.js文件,比如我們現(xiàn)在想讓登錄頁(yè)面懶加載闸准,那就把登錄頁(yè)面的路由改成這樣:

<Route path="login" component={require('react-router!./containers/Login')}/>

編譯打包后益愈,又多出了一個(gè)1.1.js文件,這就是在進(jìn)入登錄路由時(shí)要加載的文件夷家,也就是單獨(dú)的登錄組件蒸其。其它的就不用我們管了,代碼會(huì)自動(dòng)處理的库快。
既然是按需加載摸袁,我們一定是希望初始的時(shí)候加載的代碼盡量少,盡可能在進(jìn)入某個(gè)路由時(shí)才載入相應(yīng)的全部?jī)?nèi)容义屏。我們的代碼大致就三類東西:組件靠汁、action和reducer。組件很明顯可以是獨(dú)立載入的闽铐。reducer恐怕沒(méi)辦法膀曾,因?yàn)樗枰笇?dǎo)整個(gè)倉(cāng)庫(kù)狀態(tài)的建立。至于action阳啥,我們前面的示例代碼是不獨(dú)立的添谊,因?yàn)閞educer要依賴action文件里面的常量,我們只需要把所有的常量提出到一個(gè)公共的文件中察迟,只有組件引用action文件斩狱。比如我們新建一個(gè)src/constants.js文件耳高,內(nèi)容是:

// 所有action的常量...
export const INPUT_USERNAME = 'INPUT_USERNAME'
export const INPUT_PASSWORD = 'INPUT_PASSWORD'
export const RECEIVE_NEWS_LIST = 'RECEIVE_NEWS_LIST'
export const SET_KEYWORD = 'SET_KEYWORD'

然后還以login為例,把src/reducers/login.js里面引入常量的目標(biāo)改為constants.js:

import {INPUT_USERNAME, INPUT_PASSWORD} from '../constants'

src/actions/login.js里也這樣引入常量所踊。run dist后泌枪,1.1.js文件就包含了actions/login.js里面的內(nèi)容。

添加hash后綴

在一個(gè)大型且需要頻繁升級(jí)的項(xiàng)目中秕岛,靜態(tài)文件往往需要添加hash后綴碌燕,這主要是出于兩個(gè)原因:一個(gè)是所有版本的靜態(tài)文件可以同時(shí)存在,而頁(yè)面由后端控制继薛,后端根據(jù)接口的版本綁定js和css文件修壕,這樣便于升級(jí)和回滾。另一個(gè)是防止緩存遏考,這和前面圖片重命名為hash值是一個(gè)道理慈鸠。
讓webpack為文件名添加后綴非常簡(jiǎn)單,只需要在輸出的文件名上加上[hash]就可以了灌具。比如我們想讓app.js帶上hash后綴青团,只需要在cfg/dist.js最后一句前面加上一句:

config.output.filename = 'app.[hash].js'
// 或者
config.output.filename = 'app.js?v=[hash]'

而對(duì)于插件生成的樣式文件和公共js文件同樣也是在文件名上加上[hash]就行了。
現(xiàn)在關(guān)鍵的問(wèn)題是怎么應(yīng)用這些有了hash后綴的文件咖楣《桨剩總不能每打一次包我們就手動(dòng)改一下index.html把。
webpack的配置文件是js诱贿,這就意味著這個(gè)配置文件是活的娃肿,我們可以很容易把想做的事情通過(guò)代碼實(shí)現(xiàn)。現(xiàn)在我要在每次打包后把index.html文件引入的js和css文件自動(dòng)替換成帶hash尾巴的形式瘪松,只需添加一個(gè)自己寫(xiě)的插件,其實(shí)就是一個(gè)函數(shù)锨阿。在cfg/dist.js里面的plugins數(shù)組里添加以下函數(shù):

function() { 
      this.plugin("done", function(stats) { 
          let htmlPath = path.join(__dirname, '../dist/index.html') 
          let htmlText = fs.readFileSync(htmlPath, {encoding:'utf-8'}) 
          let assets = stats.toJson().assetsByChunkName
          Object.keys(assets).forEach((key)=>{ 
                let fileNames = assets[key]; 
                ['js', 'css'].forEach(function(ext){ 
                        htmlText = htmlText.replace(key+'.'+ext,
                            fileNames.find(function(item){ 
                                return new RegExp(key+'\\.\\w+\\.'+ext+'$').test(item) 
                            })) 
                }) 
          }) 
          fs.writeFileSync( htmlPath, htmlText) 
     });
}

很暴力宵睦,就是赤裸裸的node操作文件系統(tǒng)。這回dist文件夾中的index.html里引入的腳本和樣式都是帶hash的了墅诡。
在很多項(xiàng)目中壳嚎,我們前端要提供的可能不是一個(gè)引用好js和css的html文件,而是一個(gè)map文件末早,里面有靜態(tài)文件的版本信息(hash值)烟馅,這樣后端就能直接把需要的靜態(tài)文件掛上∪涣祝可以自己寫(xiě)一個(gè)跟上面代碼類似的插件輸出一個(gè)map文件郑趁,也可在萬(wàn)能的npm找個(gè)插件,比如map-json-webpack-plugin姿搜。上面那個(gè)功能也可以試試replace-webpack-plugin寡润。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末捆憎,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子梭纹,更是在濱河造成了極大的恐慌躲惰,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,635評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件变抽,死亡現(xiàn)場(chǎng)離奇詭異础拨,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)绍载,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)诡宗,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人逛钻,你說(shuō)我怎么就攤上這事僚焦。” “怎么了曙痘?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,083評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵芳悲,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我边坤,道長(zhǎng)名扛,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,640評(píng)論 1 296
  • 正文 為了忘掉前任茧痒,我火速辦了婚禮肮韧,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘旺订。我一直安慰自己弄企,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,640評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布区拳。 她就那樣靜靜地躺著拘领,像睡著了一般。 火紅的嫁衣襯著肌膚如雪樱调。 梳的紋絲不亂的頭發(fā)上约素,一...
    開(kāi)封第一講書(shū)人閱讀 52,262評(píng)論 1 308
  • 那天,我揣著相機(jī)與錄音笆凌,去河邊找鬼圣猎。 笑死,一個(gè)胖子當(dāng)著我的面吹牛乞而,可吹牛的內(nèi)容都是我干的送悔。 我是一名探鬼主播,決...
    沈念sama閱讀 40,833評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼放祟!你這毒婦竟也來(lái)了鳍怨?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,736評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤跪妥,失蹤者是張志新(化名)和其女友劉穎鞋喇,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體眉撵,經(jīng)...
    沈念sama閱讀 46,280評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡侦香,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,369評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了纽疟。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片罐韩。...
    茶點(diǎn)故事閱讀 40,503評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖污朽,靈堂內(nèi)的尸體忽然破棺而出散吵,到底是詐尸還是另有隱情,我是刑警寧澤蟆肆,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布矾睦,位于F島的核電站,受9級(jí)特大地震影響炎功,放射性物質(zhì)發(fā)生泄漏枚冗。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,870評(píng)論 3 333
  • 文/蒙蒙 一蛇损、第九天 我趴在偏房一處隱蔽的房頂上張望赁温。 院中可真熱鬧,春花似錦淤齐、人聲如沸股囊。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,340評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)稚疹。三九已至,卻和暖如春锈死,著一層夾襖步出監(jiān)牢的瞬間贫堰,已是汗流浹背穆壕。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,460評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工待牵, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人喇勋。 一個(gè)月前我還...
    沈念sama閱讀 48,909評(píng)論 3 376
  • 正文 我出身青樓缨该,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親川背。 傳聞我的和親對(duì)象是個(gè)殘疾皇子贰拿,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,512評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • GitChat技術(shù)雜談 前言 本文較長(zhǎng)蛤袒,為了節(jié)省你的閱讀時(shí)間,在文前列寫(xiě)作思路如下: 什么是 webpack膨更,它要...
    蕭玄辭閱讀 12,698評(píng)論 7 110
  • 寫(xiě)在開(kāi)頭 先說(shuō)說(shuō)為什么要寫(xiě)這篇文章, 最初的原因是組里的小朋友們看了webpack文檔后, 表情都是這樣的: (摘...
    Lefter閱讀 5,296評(píng)論 4 31
  • 無(wú)意中看到zhangwnag大佬分享的webpack教程感覺(jué)受益匪淺妙真,特此分享以備自己日后查看,也希望更多的人看到...
    小小字符閱讀 8,178評(píng)論 7 35
  • webpack 介紹 webpack 是什么 為什么引入新的打包工具 webpack 核心思想 webpack 安...
    yxsGert閱讀 6,480評(píng)論 2 71
  • 安妮寶貝的小說(shuō)我看了不少荚守,只是每次看完之后心情總會(huì)晦暗許久珍德,然而卻總是忍不住看了一遍又一遍。特別是《七月與安生》...
    精進(jìn)的醫(yī)生閱讀 542評(píng)論 6 4