Vue2+koa2構(gòu)建單頁應(yīng)用(一)- 開發(fā)環(huán)境打包與配置

之前用Vue2+webpack+express構(gòu)建單頁應(yīng)用,發(fā)現(xiàn)node端不能用es6的語法猾骡,為了前后端都用上es6的語法,node框架決定嘗試koa2

代碼地址:https://github.com/chenjiaj/Vue2-koa2-demo

一竹观、需要環(huán)境

node版本在7及以上
選擇新版本的環(huán)境是為了node端不用引入babel對(duì)es6做處理土辩,新的node版本對(duì)es6有良好的支持。

二摘符、創(chuàng)建基本項(xiàng)目

1.1 啟動(dòng)koa小項(xiàng)目demo

1.新建文件夾koa2+vue2-demo贤斜,然后進(jìn)入文件夾,打開cmd進(jìn)入文件夾內(nèi)的目錄或者webstorm的命令面板逛裤。

2.執(zhí)行npm init命令生成package.json文件,然后執(zhí)行npm install koa koa-onerror --save 下載koa和 koa-onerror

3.在項(xiàng)目根目錄下新建config文件夾,然后進(jìn)入文件夾新建config.js瘩绒,輸入以下內(nèi)容,配置端口號(hào)

module.exports = {
    node: {
    port: 3011
}

};

4.在項(xiàng)目根目錄新建app.js文件带族,然后輸入以下內(nèi)容锁荔,創(chuàng)建一個(gè)基本的項(xiàng)目

const Koa = require('koa');
const app = new Koa();
const Config = require('./config/config');
const onerror = require('koa-onerror');

//錯(cuò)誤信息處理
onerror(app);

//控制臺(tái)打印請(qǐng)求信息
app.use(async(ctx, next) => {
    const start = Date.now();
    await next();
    const ms = Date.now() - start;
    console.log(`${ctx.method} ${ctx.url} - ${ms}ms`);
});

app.listen(Config.node.port);
  1. 修改package.json,在script對(duì)象中添加 "start": "node ./app.js",如下圖所示
Paste_Image.png

6.此時(shí)在命令面板中輸入npm start即可啟動(dòng)項(xiàng)目蝙砌,然后在瀏覽器中訪問 http://localhost:3011/阳堕,因?yàn)楝F(xiàn)在還沒有對(duì)請(qǐng)求做任何處理跋理,所以返回not found。

Paste_Image.png

1.2 添加vue頁面恬总,實(shí)現(xiàn)hello world

1.在根目錄下新建src,然后在src下添加index.html文件,并且添加一個(gè)id為app的div前普,如下。同時(shí)在命令面板輸入 npm install vue --save

Paste_Image.png

2.在src目錄下新建views文件夾(存放所有的.vue文件)壹堰,并在此文件夾下添加app.vue文件拭卿。在app.vue寫入一下代碼:

<template>
    <div>hello world!</div>
</template>

3.在src下新建main.js作為vue的入口文件。在main.js中添加以下內(nèi)容:

import Vue from 'vue';
import App from './views/app.vue';

new Vue({
  el: '#app',
  render: h=> h(App)
});

現(xiàn)在目錄結(jié)構(gòu)如下:


Paste_Image.png

一個(gè)hello world 的demo就寫好了贱纠,但是要在瀏覽器看到效果峻厚,還需要引入vue包,同時(shí)也需要添加webpack打包需要的文件與配置谆焊。將vue內(nèi)容打包引入index.html中惠桃,然后再將node接收到的頁面請(qǐng)求返回打包后的index.html頁面

1.3 添加webpack打包文件與配置

1.下載webpack打包需要的依賴包

npm install webpack webpack-merge koa-webpack extract-text-webpack-plugin html-webpack-plugin css-loader file-loader vue-template-compiler vue-loader vue-style-loader  --save-dev

webpack :webpack打包需要引入的核心包

koa-webpack:封裝了webpack-dev-middleware和webpack-hot-middleware兩個(gè)插件

webpack-dev-middleware是需要webpack打包的項(xiàng)目,開發(fā)時(shí)使用的中間件懊渡,主要作用是不需要將打包生成的文件放在硬盤中刽射,而是放在內(nèi)存中,這樣可以提高開發(fā)效率剃执,而且配合webpack-hot-middleware中間件使用可以實(shí)現(xiàn)熱加載

extract-text-webpack-plugin:主要是為了抽離css樣式,防止將樣式打包在js中引起頁面樣式加載錯(cuò)亂的現(xiàn)象

html-webpack-plugin:是webpack的插件誓禁,這個(gè)插件用來簡化創(chuàng)建服務(wù)于 webpack bundle 的 HTML 文件,尤其是對(duì)于在文件名中包含了 hash 值肾档,而這個(gè)值在每次編譯的時(shí)候都發(fā)生變化的情況摹恰。你既可以讓這個(gè)插件來幫助你自動(dòng)生成 HTML 文件,也可以使用 lodash 模板加載生成的 bundles怒见,或者自己加載這些 bundles俗慈。

vue-loader:是webpack的loader,能夠?qū)?vue文件轉(zhuǎn)換成js文件

vue-html-loader、vue-template-compiler遣耍、css-loader闺阱、vue-style-loader:這三個(gè)都是webpack的loader,都是將.vue文件轉(zhuǎn)換成js文件的依賴

2.下載babel需要的依賴包

npm install babel-core babel-loader babel-plugin-transform-runtime babel-polyfill babel-preset-es2015 babel-preset-stage-0 babel-runtime   --save-dev

以babel-開頭:都是用于兼容es6寫法,將es6的代碼轉(zhuǎn)換成es5的代碼
babel-core舵变、babel-loader:babel配合webpack工具使用必須要引入的
babel-plugin-transform-runtime酣溃、babel-runtime:解決重復(fù)出現(xiàn)在一些模塊里,導(dǎo)致編譯后的代碼體積變大的問題纪隙。
babel-preset-es2015:將 ES2015 編譯成 ES5
babel-preset-stage-2:除了覆蓋stage-3的所有功能,不是對(duì)ES6功能的增加赊豌,而是為了增強(qiáng)代碼的可讀性和可修改性而提出的參考:http://babeljs.io/docs/setup/#installation

3.在根目錄下添加.babelrc文件,添加以下配置:

    {
          "presets": ["es2015","stage-0"],
          "plugins": ["transform-runtime"],
          "comments": false
     }

4.在根目錄下新建build文件夾绵咱,然后添加webpack.base.conf.js碘饼、webpack.dev.conf.js、webpack.prod.conf.js
webpack.base.conf.js:開發(fā)和生成環(huán)境相同配置寫字這個(gè)里邊
webpack.dev.conf.js:針對(duì)開發(fā)時(shí)配置的文件
webpack.prod.conf.js:針對(duì)生產(chǎn)環(huán)境(正式上線)配置的文件

5.在webpack.base.conf.js中添加以下配置

 /* 引入操作路徑模塊和webpack */
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');

module.exports = {
/* 輸入文件 */
entry: {
    index: ['babel-polyfill', path.resolve(__dirname, '../src/main.js')]
},
output: {
    /* 輸出目錄,沒有則新建 */
    path: path.resolve(__dirname, '../dist'),
    /* 靜態(tài)目錄艾恼,可以直接從這里取文件 */
    publicPath: '/',
    /* 文件名 */
    filename: 'js/[name].[hash].js',
    chunkFilename: 'js/[name].[chunkhash].js'
},
module: {
    rules: [{
        test: /\.vue$/,
        loader: 'vue-loader',
        options: {
            loaders: {
                css: ExtractTextPlugin.extract({
                    use: 'css-loader',
                    fallback: 'vue-style-loader' // <- this is a dep of vue-loader, so no need to explicitly install if using npm3
                })
            }
        }
    }, {//頁面中import css文件打包需要用到
        test: /\.css/,
        loader: ExtractTextPlugin.extract({ fallback: 'style-loader', use: 'css-loader' })
    }, {
        test: /\.js$/,
        loader: 'babel-loader',
        /* 排除模塊安裝目錄的文件 */
        exclude: /node_modules/
    },{
        test: /\.png$|\.jpg$|\.gif$|\.ico$/,
        loader: "file-loader",
        exclude: /node_modules/
    }]
},
plugins: [
    new HtmlWebpackPlugin({
        filename: 'index.html',
        template: path.resolve(__dirname, '../src/index.html'),
        inject: true
    }),
    new ExtractTextPlugin("style.css")
]

};

6.我們先配置開發(fā)是需要文件住涉,生成環(huán)境之后再近些配置。
首先在webpack.dev.conf.js中添加

const merge = require('webpack-merge');
const baseConfig = require('./webpack.base.conf');
const webpack = require('webpack');

let devConfig =  merge(baseConfig, {
output: {
    path: '/'
},
plugins: [
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NoEmitOnErrorsPlugin()
]
});

module.exports = devConfig;

7.然后在app.js中添加webpack配置蒂萎,如下

Paste_Image.png

8.然后運(yùn)行npm start啟動(dòng)項(xiàng)目秆吵,看到打印出一下日志,證明啟動(dòng)成功

Paste_Image.png

9.在瀏覽器中訪問http://localhost:3011/五慈,效果如下,vue + koa構(gòu)建一個(gè)hello world的小項(xiàng)目就成功了主穗。

Paste_Image.png

三泻拦、添加路由實(shí)現(xiàn)單頁

1.1 vue添加路由

1.下載路由的依賴包 npm install vue-router --save

2.在src文件夾下添加router文件夾,然后新建index.js,存放路由主要配置

3.在views文件夾下忽媒,添加example文件争拐,然后添加兩個(gè)文件,分別是example.vue和example1.vue晦雨,作為路由中的兩個(gè)頁面架曹。分別添加以下內(nèi)容:

Paste_Image.png
Paste_Image.png

4.在router下的index.js編輯以下內(nèi)容:

Paste_Image.png

5.修改main.js如下,將路由:

Paste_Image.png

6.修改app.vue闹瞧,配置的路由中的compent將顯示在router-view中

Paste_Image.png

7.刷新瀏覽器绑雄,可以看到以下效果

Paste_Image.png

點(diǎn)擊example1將顯示(點(diǎn)擊example1跳轉(zhuǎn)并未刷新頁面,只是vue的路由跳轉(zhuǎn))

.

8.但是在http://localhost:3011/example1下刷新瀏覽器奥邮,現(xiàn)在會(huì)發(fā)現(xiàn)找不到

Paste_Image.png

這是什么原因造成的呢万牺?

因?yàn)関ue的路由是在瀏覽器中進(jìn)行管理,如果刷新http://localhost:3011/時(shí)可以訪問到的洽腺,因?yàn)檎?qǐng)求/路徑脚粟,node將其指向了index.html(因?yàn)閣ebpack打包會(huì)把index.html打包到根目錄,而koa-webpack在沒有傳遞參數(shù)的情況下也是指向的webpack配置文件中output中的publicPath蘸朋,配置文件中配置的是/核无,所以默認(rèn)/請(qǐng)求指向index.html),以下是koa-webpack中默認(rèn)配置的源代碼

![Paste_Image.png](http://upload-images.jianshu.io/upload_images/1210894-bb4f6395ba003114.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240z

而/example1請(qǐng)求到node,node會(huì)去尋找node端的路由處理藕坯,因?yàn)閚ode端沒有配置這個(gè)路由团南,所有找不到。

如果想要訪問到/example1堕担,需要請(qǐng)求到index.html,然后由vue的路由處理找到對(duì)應(yīng)的模塊

解決方法有:

(1)vue路由采用hash模式已慢,修改router下的index.js文件,將mode的值改為hash霹购,如果是hash佑惠,但是這樣瀏覽器路徑會(huì)變成http://localhost:3011/#/example1,有一點(diǎn)丑陋,http://localhost:3011/#/example1這個(gè)路徑還是請(qǐng)求的/后面的會(huì)被當(dāng)做參數(shù)處理

Paste_Image.png

(2)將所有html請(qǐng)求轉(zhuǎn)到index.html 然后讓vue的瀏覽器處理

1.2 配置node端端

1.將所有的html請(qǐng)求轉(zhuǎn)到index.html,有一個(gè)現(xiàn)成的插件connect-history-api-fallback替我們做了這件事膜楷,但是需要稍微封裝一下才能在koa2中使用旭咽。
(1)npm install connect-history-api-fallback --save 下載插件包
(2)在根目錄下添加middleware文件夾,用于存放koa的中間件
(3)在middleware文件夾中添加koa2-connect-history-api-fallback.js 文件赌厅,koa2中間件需要傳入需要的方法穷绵,所以封裝返回了一個(gè)方法

    const history = require('connect-history-api-fallback');
    module.exports = options=> {
        const middleware = history(options);
        const noop = ()  => {
        };

        return async (ctx, next)=> {
          middleware(ctx, null, noop);
        await next();
        };
    };

2.在app.js添加const history = require('./middleware/koa2-connect-history-api-fallback');和
app.use(history({
verbose: true//打出轉(zhuǎn)發(fā)日志
}));
注意:app.use(history(...))要寫在app.use(middleware({...}))之前,不然koa-webpack已經(jīng)返回not found了特愿,app.use(history(...))就不會(huì)生效了

11.寫好之后重啟服務(wù)仲墨,然后訪問瀏覽器刷新http://localhost:3011/example1就可以訪問到了
并且可以看到日志,只有請(qǐng)求html轉(zhuǎn)到了index.html

Paste_Image.png

1.3 優(yōu)化

1.添加less配置揍障,讓.vue文件支持寫less文件

(1)下載less打包編譯需要的依賴目养,npm install less less-loader --save-dev
(2)在webpack.base.conf.js中配置,添加這兩個(gè)配置毒嫡,將會(huì)識(shí)別.vue里邊的less,也可以將less寫成單獨(dú)的文件

Paste_Image.png

(3)在頁面中引入less文件(通常便于維護(hù)癌蚁,less寫在單獨(dú)文件中)
在src文件夾中添加static文件夾,然后在static文件夾中添加less文件兜畸,專門存放less文件努释,然后添加example.less文件,順便寫一些樣式進(jìn)去咬摇,如下

Paste_Image.png

然后在example.vue文件中引入這個(gè)less文件

Paste_Image.png

頁面效果如下

Paste_Image.png

2.實(shí)現(xiàn)懶加載伐蒂,優(yōu)化初始化加載

在頁面比較多的時(shí)瓦堵,單頁應(yīng)用按照之前的方式打包成一個(gè)js會(huì)導(dǎo)致首頁加載時(shí)很慢澎剥,為了解決這個(gè)問題,可以修改打包锈拨,讓首頁只加載通用代碼和首頁要用到的代碼龄坪,跳轉(zhuǎn)到其他頁面再加載對(duì)應(yīng)頁面的js昭雌,這樣可以解決項(xiàng)目較大首頁加載緩慢的問題。

修改router中index.js,將.vue文件加載改為
const Example = r => require.ensure([], () => r(require('../views/example/example.vue')), 'Example');
const Example1 = r => require.ensure([], () => r(require('../views/example/example1.vue')), 'Example1');

因?yàn)閣ebpack.base.conf.js已經(jīng)加了chunkFilename: 'js/[name].[chunkhash].js'健田,所以不用再修改webpack配置

Paste_Image.png

瀏覽頁面烛卧,這個(gè)時(shí)候會(huì)發(fā)現(xiàn),訪問example頁面只有example.js

Paste_Image.png

點(diǎn)擊example1頁面妓局,才會(huì)新加入example1.js总放,并且加載之后,以后返回example1頁面不會(huì)重新加載好爬,提高性能

Paste_Image.png

經(jīng)過以上步驟局雄,我們已經(jīng)可以在本地跑起來開發(fā)vue項(xiàng)目了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末存炮,一起剝皮案震驚了整個(gè)濱河市炬搭,隨后出現(xiàn)的幾起案子蜈漓,更是在濱河造成了極大的恐慌,老刑警劉巖宫盔,帶你破解...
    沈念sama閱讀 206,968評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件融虽,死亡現(xiàn)場離奇詭異,居然都是意外死亡灼芭,警方通過查閱死者的電腦和手機(jī)有额,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來彼绷,“玉大人巍佑,你說我怎么就攤上這事〖拿酰” “怎么了句狼?”我有些...
    開封第一講書人閱讀 153,220評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長热某。 經(jīng)常有香客問我,道長胳螟,這世上最難降的妖魔是什么昔馋? 我笑而不...
    開封第一講書人閱讀 55,416評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮糖耸,結(jié)果婚禮上秘遏,老公的妹妹穿的比我還像新娘。我一直安慰自己嘉竟,他們只是感情好邦危,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評(píng)論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著舍扰,像睡著了一般倦蚪。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上边苹,一...
    開封第一講書人閱讀 49,144評(píng)論 1 285
  • 那天陵且,我揣著相機(jī)與錄音,去河邊找鬼个束。 笑死慕购,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的茬底。 我是一名探鬼主播沪悲,決...
    沈念sama閱讀 38,432評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼阱表!你這毒婦竟也來了殿如?” 一聲冷哼從身側(cè)響起贡珊,我...
    開封第一講書人閱讀 37,088評(píng)論 0 261
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎握截,沒想到半個(gè)月后飞崖,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,586評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡谨胞,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評(píng)論 2 325
  • 正文 我和宋清朗相戀三年固歪,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片胯努。...
    茶點(diǎn)故事閱讀 38,137評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡牢裳,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出叶沛,到底是詐尸還是另有隱情蒲讯,我是刑警寧澤,帶...
    沈念sama閱讀 33,783評(píng)論 4 324
  • 正文 年R本政府宣布灰署,位于F島的核電站判帮,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏溉箕。R本人自食惡果不足惜晦墙,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望肴茄。 院中可真熱鬧晌畅,春花似錦、人聲如沸寡痰。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽拦坠。三九已至连躏,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間贪婉,已是汗流浹背反粥。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評(píng)論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留疲迂,地道東北人才顿。 一個(gè)月前我還...
    沈念sama閱讀 45,595評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像尤蒿,于是被迫代替她去往敵國和親郑气。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評(píng)論 2 345

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