基于 Egg + Vue + Webpack3/Webpack2 多页面和单页面服务端客户端渲染同构工程骨架项目.
easywebpack-vue
版本为 3.0.0, Webpack2 版本项目骨架请见 feature/webpack2
分支, 对应 easywebpack-vue
版本为 1.x.x支持服务端渲染, 前端渲染, 静态页面渲染三种方式,
支持单页面, 多页面服务端渲染,前端渲染模式
支持 server 和 client 端代码修改, Webpack 时时编译和热更新, npm start
一键启动应用
基于 vue + axios 多页面服务端渲染, 客户端渲染同构实现
基于 vue + vuex + vue-router + axios 单页面服务器客户端同构实现
基于easywebpack基础配置, 使用es6 class 继承方式编写webpack配置 和 cli 构建
支持Js/Css/Image资源依赖, 内置支持CDN特性
支持css/sass/less样式编写
支持根据.vue文件自动创建entry入口文件
支持Vue组件异步加载, 具体实例请看app/web/page/dynamic
支持vue 2.3 官方VueSSRPlugin实现方案,代码分支feature/VueSSRPlugin
支持Node 4+ 以上版本, 包括Node 8 版本的async和await特性
npm install easywebpack-cli -g
npm install
npm start
npm start
应用访问: http://127.0.0.1:7001
// 直接运行(编译文件全部在内存里面,本地开发使用)
npm start
// 编译文件到磁盘打包使用(发布测试环境)
npm run build-dev 或者 easywebpack build dev
// 编译文件到磁盘打包使用(发布正式环境)
npm run build 或者 easywebpack build prod
easywebpack-cli
根据 webpack.config.js
自动创建Webpack Config`config/config.local.js`
const EasyWebpack = require('easywebpack-vue');
exports.webpack = {
webpackConfigList:EasyWebpack.getWebpackConfig()
};
编写配置请见 tag 1.0.0
build目录代码实现
`config/config.local.js`
exports.webpack = {
webpackConfigList: [
require(path.join(app.baseDir, 'build/client')), // http://127.0.0.1:9000
require(path.join(app.baseDir, 'build/server')), // http://127.0.0.1:9001
]
};
构建会同时启动两个webpack构建服务, 客户端js构建(build/client), 服务端构建(build/server), 默认端口9000, webpackConfigList 端口依次递增.
├── app
│ ├── controller
│ │ ├── test
│ │ │ └── test.js
│ ├── extend
│ ├── lib
│ ├── middleware
│ ├── mocks
│ ├── proxy
│ ├── router.js
│ ├── view
│ │ ├── about // 服务器编译的jsbundle文件
│ │ │ └── about.js
│ │ ├── home
│ │ │ └── home.js // 服务器编译的jsbundle文件
│ │ └── layout // 用于根据指定的layout生成对应的html页面, 用于服务器渲染失败时,采用客户端渲染
│ │ └── layout.html
│ └── web // 前端工程目录
│ ├── asset // 存放公共js,css资源
│ ├── framework // 前端公共库和第三方库
│ │ ├── fastclick
│ │ │ └── fastclick.js
│ │ ├── sdk
│ │ │ ├── sdk.js
│ │ ├── storage
│ │ │ └── storage.js
│ │ └── vue // 与vue相关的公开代码
│ │ ├── app.js // 前后端调用入口, 默认引入componet/directive/filter
│ │ ├── component.js // 组件入口, 可以增加component目录,类似下面的directive
│ │ ├── directive // directive 目录,存放各种directive组件
│ │ ├── directive.js // directive引用入口
│ │ └── filter.js // filter引用入口
│ ├── page // 前端页面和webpack构建目录, 也就是webpack打包配置entryDir
│ │ ├── home // 每个页面遵循目录名, js文件名, scss文件名, vue文件名相同
│ │ │ ├── home.scss
│ │ │ ├── home.vue
│ │ │ ├── images // 页面自有图片,公共图片和css放到asset下面
│ │ │ │ └── icon_more.png
│ │ │ └── w-week // 页面自有组件,公共组件放到widget下面
│ │ │ ├── w-week.scss
│ │ │ └── w-week.vue
│ │ └── test // 每个页面遵循目录名, js文件名, scss文件名, vue文件名相同
│ │ └── test.vue
│ ├── store // 引入vuex 的基本规范, 可以分模块
│ │ ├── app
│ │ │ ├── actions.js
│ │ │ ├── getters.js
│ │ │ ├── index.js
│ │ │ ├── mutation-type.js
│ │ │ └── mutations.js
│ │ └── store.js
│ └── component // 公共业务组件, 比如loading, toast等, 遵循目录名, js文件名, scss文件名, vue文件名相同
│ ├── loading
│ │ ├── loading.scss
│ │ └── loading.vue
│ ├── test
│ │ ├── test.vue
│ │ └── test.scss
│ └── toast
│ ├── toast.scss
│ └── toast.vue
├── build // webpack 自定义配置入口, 会与默认配置进行合并(看似这么多,其实这里只是占个位说明一下)
│ ├── base
│ │ └── index.js // 公共配置
│ ├── client // 客户端webpack编译配置
│ │ ├── dev.js
│ │ ├── prod.js
│ │ └── index.js
│ ├── server // 服务端webpack编译配置
│ │ ├── dev.js
│ │ ├── prod.js
│ │ └── index.js
│ └── index.js
├── config
│ ├── config.default.js
│ ├── config.local.js
│ ├── config.prod.js
│ ├── config.test.js
│ └── plugin.js
├── doc
├── index.js
├── public // webpack编译目录结构, render文件查找目录
│ ├── manifest.json // 资源依赖表
│ ├── static
│ │ ├── css
│ │ │ ├── home
│ │ │ │ ├── home.07012d33.css
│ │ │ └── test
│ │ │ ├── test.4bbb32ce.css
│ │ ├── img
│ │ │ ├── change_top.4735c57.png
│ │ │ └── intro.0e66266.png
│ ├── test
│ │ └── test.js
│ └── vendor.js // 生成的公共打包库
支持多页面/单页面服务端渲染, 前端渲染, 静态页面三种方式.
在app/web/page 目录下面创建home目录, home.vue 文件, Webpack自动根据.vue文件创建entry入口, 具体实现请见webpack.config.js
<template>
<layout title="基于egg-vue-webpack-dev和egg-view-vue插件的工程示例项目" description="vue server side render" keywords="egg, vue, webpack, server side render">
{{message}}
</layout>
</template>
<style>
@import "home.css";
</style>
<script type="text/babel">
export default {
components: {
},
computed: {
},
methods: {
},
mounted() {
}
}
</script>
egg-view-vue-ssr
插件 render
方法实现exports.index = function* (ctx) {
yield ctx.render('home/home.js', { message: 'vue server side render!' });
};
app.get('/home', app.controller.home.home.index);
egg-view-vue-ssr
插件 renderClient
方法实现exports.client = function* (ctx) {
yield ctx.renderClient('home/home.js', { message: 'vue server side render!' });
};
app.get('/client', app.controller.home.home.client);
直接有easywebpack构建出静态HTML文件, 请见 webpack.config.js
配置和 app/web/page/html
代码实现
通过 egg-static
静态文件访问HTML文件
在app/web/page 目录下面创建app目录, app.vue, app.js 文件.
<template>
<app-layout>
<transition name="fade" mode="out-in">
<router-view></router-view>
</transition>
</app-layout>
</template>
<style lang="sass">
</style>
<script type="text/babel">
export default {
computed: {
},
mounted(){
}
}
</script>
import { sync } from 'vuex-router-sync';
import store from 'store/app';
import router from 'component/app/router';
import app from './app.vue';
import App from 'app';
import Layout from 'component/layout/app';
App.component(Layout.name, Layout);
sync(store, router);
export default App.init({
base: '/app',
...app,
router,
store
});
exports.index = function* (ctx) {
yield ctx.render('app/app.js', { url: this.url.replace(/\/app/, '') });
};
app.get('/app(/.+)?', app.controller.app.app.index);
npm start
启动流程