之前用Vue2+webpack+express構建單頁應用,發現node端不能用es6的語法,為了前后端都用上es6的語法,node框架決定嘗試koa2
代碼地址:https://github.com/chenjiaj/Vue2-koa2-demo
一、需要環境
node版本在7及以上
選擇新版本的環境是為了node端不用引入babel對es6做處理,新的node版本對es6有良好的支持。
二、創建基本項目
1.1 啟動koa小項目demo
1.新建文件夾koa2+vue2-demo,然后進入文件夾,打開cmd進入文件夾內的目錄或者webstorm的命令面板。
2.執行npm init命令生成package.json文件,然后執行npm install koa koa-onerror --save 下載koa和 koa-onerror
3.在項目根目錄下新建config文件夾,然后進入文件夾新建config.js,輸入以下內容,配置端口號
module.exports = {
node: {
port: 3011
}
};
4.在項目根目錄新建app.js文件,然后輸入以下內容,創建一個基本的項目
const Koa = require('koa');
const app = new Koa();
const Config = require('./config/config');
const onerror = require('koa-onerror');
//錯誤信息處理
onerror(app);
//控制臺打印請求信息
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);
- 修改package.json,在script對象中添加 "start": "node ./app.js",如下圖所示
6.此時在命令面板中輸入npm start即可啟動項目,然后在瀏覽器中訪問 http://localhost:3011/,因為現在還沒有對請求做任何處理,所以返回not found。
1.2 添加vue頁面,實現hello world
1.在根目錄下新建src,然后在src下添加index.html文件,并且添加一個id為app的div,如下。同時在命令面板輸入 npm install vue --save
2.在src目錄下新建views文件夾(存放所有的.vue文件),并在此文件夾下添加app.vue文件。在app.vue寫入一下代碼:
<template>
<div>hello world!</div>
</template>
3.在src下新建main.js作為vue的入口文件。在main.js中添加以下內容:
import Vue from 'vue';
import App from './views/app.vue';
new Vue({
el: '#app',
render: h=> h(App)
});
現在目錄結構如下:
一個hello world 的demo就寫好了,但是要在瀏覽器看到效果,還需要引入vue包,同時也需要添加webpack打包需要的文件與配置。將vue內容打包引入index.html中,然后再將node接收到的頁面請求返回打包后的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兩個插件
webpack-dev-middleware是需要webpack打包的項目,開發時使用的中間件,主要作用是不需要將打包生成的文件放在硬盤中,而是放在內存中,這樣可以提高開發效率,而且配合webpack-hot-middleware中間件使用可以實現熱加載
extract-text-webpack-plugin:主要是為了抽離css樣式,防止將樣式打包在js中引起頁面樣式加載錯亂的現象
html-webpack-plugin:是webpack的插件,這個插件用來簡化創建服務于 webpack bundle 的 HTML 文件,尤其是對于在文件名中包含了 hash 值,而這個值在每次編譯的時候都發生變化的情況。你既可以讓這個插件來幫助你自動生成 HTML 文件,也可以使用 lodash 模板加載生成的 bundles,或者自己加載這些 bundles。
vue-loader:是webpack的loader,能夠將.vue文件轉換成js文件
vue-html-loader、vue-template-compiler、css-loader、vue-style-loader:這三個都是webpack的loader,都是將.vue文件轉換成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的代碼轉換成es5的代碼
babel-core、babel-loader:babel配合webpack工具使用必須要引入的
babel-plugin-transform-runtime、babel-runtime:解決重復出現在一些模塊里,導致編譯后的代碼體積變大的問題。
babel-preset-es2015:將 ES2015 編譯成 ES5
babel-preset-stage-2:除了覆蓋stage-3的所有功能,不是對ES6功能的增加,而是為了增強代碼的可讀性和可修改性而提出的參考: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:開發和生成環境相同配置寫字這個里邊
webpack.dev.conf.js:針對開發時配置的文件
webpack.prod.conf.js:針對生產環境(正式上線)配置的文件
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'),
/* 靜態目錄,可以直接從這里取文件 */
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.我們先配置開發是需要文件,生成環境之后再近些配置。
首先在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配置,如下
8.然后運行npm start啟動項目,看到打印出一下日志,證明啟動成功
9.在瀏覽器中訪問http://localhost:3011/,效果如下,vue + koa構建一個hello world的小項目就成功了。
三、添加路由實現單頁
1.1 vue添加路由
1.下載路由的依賴包 npm install vue-router --save
2.在src文件夾下添加router文件夾,然后新建index.js,存放路由主要配置
3.在views文件夾下,添加example文件,然后添加兩個文件,分別是example.vue和example1.vue,作為路由中的兩個頁面。分別添加以下內容:
4.在router下的index.js編輯以下內容:
5.修改main.js如下,將路由:
6.修改app.vue,配置的路由中的compent將顯示在router-view中
7.刷新瀏覽器,可以看到以下效果
點擊example1將顯示(點擊example1跳轉并未刷新頁面,只是vue的路由跳轉)
8.但是在http://localhost:3011/example1下刷新瀏覽器,現在會發現找不到
這是什么原因造成的呢?
因為vue的路由是在瀏覽器中進行管理,如果刷新http://localhost:3011/時可以訪問到的,因為請求/路徑,node將其指向了index.html(因為webpack打包會把index.html打包到根目錄,而koa-webpack在沒有傳遞參數的情況下也是指向的webpack配置文件中output中的publicPath,配置文件中配置的是/,所以默認/請求指向index.html),以下是koa-webpack中默認配置的源代碼
vue路由采用hash模式,修改router下的index.js文件,將mode的值改為hash,如果是hash,但是這樣瀏覽器路徑會變成http://localhost:3011/#/example1,有一點丑陋,http://localhost:3011/#/example1這個路徑還是請求的/后面的會被當做參數處理
(2)將所有html請求轉到index.html 然后讓vue的瀏覽器處理
1.2 配置node端端
1.將所有的html請求轉到index.html,有一個現成的插件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中間件需要傳入需要的方法,所以封裝返回了一個方法
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//打出轉發日志
}));
注意:app.use(history(...))要寫在app.use(middleware({...}))之前,不然koa-webpack已經返回not found了,app.use(history(...))就不會生效了
11.寫好之后重啟服務,然后訪問瀏覽器刷新http://localhost:3011/example1就可以訪問到了
并且可以看到日志,只有請求html轉到了index.html
1.3 優化
1.添加less配置,讓.vue文件支持寫less文件
(1)下載less打包編譯需要的依賴,npm install less less-loader --save-dev
(2)在webpack.base.conf.js中配置,添加這兩個配置,將會識別.vue里邊的less,也可以將less寫成單獨的文件
(3)在頁面中引入less文件(通常便于維護,less寫在單獨文件中)
在src文件夾中添加static文件夾,然后在static文件夾中添加less文件,專門存放less文件,然后添加example.less文件,順便寫一些樣式進去,如下
然后在example.vue文件中引入這個less文件
頁面效果如下
2.實現懶加載,優化初始化加載
在頁面比較多的時,單頁應用按照之前的方式打包成一個js會導致首頁加載時很慢,為了解決這個問題,可以修改打包,讓首頁只加載通用代碼和首頁要用到的代碼,跳轉到其他頁面再加載對應頁面的js,這樣可以解決項目較大首頁加載緩慢的問題。
修改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');
因為webpack.base.conf.js已經加了chunkFilename: 'js/[name].[chunkhash].js',所以不用再修改webpack配置
瀏覽頁面,這個時候會發現,訪問example頁面只有example.js
點擊example1頁面,才會新加入example1.js,并且加載之后,以后返回example1頁面不會重新加載,提高性能
經過以上步驟,我們已經可以在本地跑起來開發vue項目了。