├── koa-app
├── test
│ └── test.js
├── app
│ ├── index.js
│ ├── controller
│ │ └── User.js
│ ├── router
│ │ ├── user.js
│ │ └── index.js
│ ├── middleWares
│ │ ├── static.js
│ │ ├── index.js
│ │ ├── error.js
│ │ └── limitFlow.js
│ ├── db
│ │ └── index.js
│ ├── app.js
│ ├── model
│ │ └── UserModel.js
│ └── plugins
│ │ └── http.js
├── .babelrc
├── app.config.js
├── pm2.config.js
├── package.json
└── README.md
├── webpack
├── test
│ ├── example.txt
│ ├── functions.test.js
│ ├── loader.test.js
│ └── compiler.js
├── loaders
│ ├── ms.js
│ ├── ml-loader.js
│ └── ms-plugin.js
├── src
│ ├── index.js
│ ├── functions.js
│ └── index.css
├── .babelrc
├── package.json
└── webpack.config.js
├── webpack3-basic-config
├── client
│ ├── view
│ │ ├── test.css
│ │ ├── test-styl.styl
│ │ └── index.vue
│ ├── app.vue
│ ├── assets
│ │ ├── images
│ │ │ └── logo.png
│ │ └── css
│ │ │ └── common.css
│ ├── routes.js
│ ├── index.js
│ ├── config.js
│ └── router.js
├── .eslintignore
├── .eslintrc.js
├── favicon.ico
├── doc
│ ├── images
│ │ ├── koa2.jpg
│ │ └── catalog.png
│ └── npm包说明.md
├── public
│ └── favicon.ico
├── .babelrc
├── constants.js
├── config
│ ├── utils
│ │ ├── http
│ │ │ ├── index.js
│ │ │ └── http.js
│ │ ├── staticMiddleWare.js
│ │ ├── logger
│ │ │ ├── koa-logger.js
│ │ │ └── vue-logger.js
│ │ ├── errorMiddleWare.js
│ │ ├── env.js
│ │ ├── setCookieMiddleWare.js
│ │ ├── StringUtils.js
│ │ ├── responsiveDesign.js
│ │ ├── token.js
│ │ ├── httpMiddleWare.js
│ │ ├── spaMiddleWare.js
│ │ └── proxyMiddleWare.js
│ ├── index.js
│ ├── postcss.conf.js
│ ├── vue-loader.conf.js
│ ├── webpack.config.dev.js
│ ├── koa-prod-server.js
│ ├── webpack.config.prod.js
│ ├── koa-dev-server.js
│ ├── eslintrc.conf.js
│ └── webpack.config.base.js
├── server.config.js
├── app.config.js
├── index.template.ejs
└── package.json
├── webpack4-basic-config
├── .eslintignore
├── src
│ ├── components
│ │ └── index.js
│ ├── app.vue
│ ├── routes.js
│ ├── store
│ │ ├── index.js
│ │ └── modules
│ │ │ └── test.js
│ ├── views
│ │ └── business
│ │ │ ├── bus-detial.vue
│ │ │ ├── routes.js
│ │ │ └── bus-add-edit.vue
│ ├── router.js
│ ├── index.js
│ ├── config.js
│ └── utils
│ │ ├── storage
│ │ └── README.md
│ │ └── db
│ │ └── index.js
├── README.md
├── .eslintrc.js
├── favicon.ico
├── postcss.config.js
├── config
│ ├── index.js
│ ├── utils
│ │ ├── http
│ │ │ ├── index.js
│ │ │ └── http.js
│ │ ├── staticMiddleWare.js
│ │ ├── logger
│ │ │ ├── koa-logger.js
│ │ │ └── vue-logger.js
│ │ ├── errorMiddleWare.js
│ │ ├── env.js
│ │ ├── StringUtils.js
│ │ ├── responsiveDesign.js
│ │ ├── token.js
│ │ ├── spaMiddleWare.js
│ │ └── proxyMiddleWare.js
│ ├── webpack.config.dll.js
│ ├── webpack.config.dev.js
│ ├── webpack.config.prod.js
│ ├── koa-dev-server.js
│ ├── eslintrc.conf.js
│ └── webpack.config.base.js
├── .babelrc
├── constants.js
├── app.config.js
├── vendors-manifest.json
├── index.template.ejs
└── package.json
├── react-base-webpack
├── README.md
├── .eslintrc.js
├── client
│ ├── router.js
│ ├── view
│ │ ├── login.js
│ │ └── index.js
│ ├── App.js
│ ├── components
│ │ └── privateRoute
│ │ │ └── index.js
│ ├── index.js
│ └── utils
│ │ └── Session.js
├── favicon.ico
├── constants.js
├── config
│ ├── index.js
│ ├── middle
│ │ ├── staticMiddleWare.js
│ │ ├── errorMiddleWare.js
│ │ ├── proxyToken.js
│ │ ├── spaMiddleWare.js
│ │ └── proxyMiddleWare.js
│ ├── logger
│ │ └── koa-logger.js
│ ├── http
│ │ └── http.js
│ ├── webpack.config.dev.js
│ ├── koa.server.js
│ ├── webpack.config.base.js
│ ├── webpack.config.prod.js
│ └── eslintrc.conf.js
├── postcss.config.js
├── app.config.js
├── .babelrc
├── index.template.ejs
└── package.json
├── webpack4-ssr-config
├── .eslintrc.js
├── client
│ ├── app.vue
│ ├── assets
│ │ ├── images
│ │ │ ├── 01.jpg
│ │ │ └── logo.png
│ │ └── css
│ │ │ └── reset.css
│ ├── plugins
│ │ └── index.js
│ ├── store
│ │ ├── index.js
│ │ └── modules
│ │ │ └── test.js
│ ├── views
│ │ ├── test
│ │ │ ├── routes.js
│ │ │ ├── data.vue
│ │ │ └── ajax.vue
│ │ └── home.vue
│ ├── routes.js
│ ├── router.js
│ ├── utils
│ │ └── title.js
│ ├── index.js
│ ├── config.js
│ ├── entry-client.js
│ ├── entry-server.js
│ └── components
│ │ └── ProgressBar.vue
├── favicon.ico
├── dist
│ └── favicon.ico
├── config
│ ├── index.js
│ ├── http
│ │ ├── index.js
│ │ └── http.js
│ ├── middle
│ │ ├── staticMiddleWare.js
│ │ ├── errorMiddleWare.js
│ │ └── proxyMiddleWare.js
│ ├── logger
│ │ ├── koa-logger.js
│ │ └── vue-logger.js
│ ├── webpack.client.config.js
│ ├── koa.server.js
│ ├── webpack.server.config.js
│ ├── vue.koa.ssr.js
│ ├── setup.dev.server.js
│ └── eslintrc.conf.js
├── postcss.config.js
├── constants.js
├── .babelrc
├── app.config.js
├── pm2.config.js
├── index.template.ejs
├── package.json
└── pm2.md
├── .gitignore
└── README.md
/koa-app/test/test.js:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/webpack/test/example.txt:
--------------------------------------------------------------------------------
1 | Hey [name]!
2 |
--------------------------------------------------------------------------------
/webpack3-basic-config/client/view/test.css:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/webpack/loaders/ms.js:
--------------------------------------------------------------------------------
1 | console.log('这里是ms')
2 |
--------------------------------------------------------------------------------
/webpack3-basic-config/client/view/test-styl.styl:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/webpack3-basic-config/.eslintignore:
--------------------------------------------------------------------------------
1 | /node_module/*
2 | /config/*
--------------------------------------------------------------------------------
/webpack4-basic-config/.eslintignore:
--------------------------------------------------------------------------------
1 | /node_module/*
2 | /config/*
--------------------------------------------------------------------------------
/webpack4-basic-config/src/components/index.js:
--------------------------------------------------------------------------------
1 | export default []
--------------------------------------------------------------------------------
/react-base-webpack/README.md:
--------------------------------------------------------------------------------
1 | # Webpack4 + React + Koa2 构建spa应用
2 |
--------------------------------------------------------------------------------
/webpack4-basic-config/README.md:
--------------------------------------------------------------------------------
1 | # Webpack4 + Vue2 + Koa2 构建spa应用
2 |
--------------------------------------------------------------------------------
/webpack/src/index.js:
--------------------------------------------------------------------------------
1 | import './index.css'
2 |
3 | console.log('hello world')
4 |
--------------------------------------------------------------------------------
/react-base-webpack/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = require('./config/eslintrc.conf.js')
--------------------------------------------------------------------------------
/react-base-webpack/client/router.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by zdliuccit on 18/11/1.
3 | */
--------------------------------------------------------------------------------
/webpack3-basic-config/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = require('./config/eslintrc.conf.js')
--------------------------------------------------------------------------------
/webpack4-basic-config/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = require('./config/eslintrc.conf.js')
--------------------------------------------------------------------------------
/webpack4-ssr-config/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = require('./config/eslintrc.conf.js')
--------------------------------------------------------------------------------
/webpack4-basic-config/src/app.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/webpack/src/functions.js:
--------------------------------------------------------------------------------
1 | export default {
2 | sum(a, b) {
3 | return a + b;
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/webpack3-basic-config/client/app.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/webpack4-ssr-config/client/app.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/koa-app/app/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * app入口文件
3 | */
4 | require('@babel/register')
5 | require('./app.js')
6 |
--------------------------------------------------------------------------------
/react-base-webpack/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zdliuccit/vue-webpack-config/HEAD/react-base-webpack/favicon.ico
--------------------------------------------------------------------------------
/webpack4-ssr-config/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zdliuccit/vue-webpack-config/HEAD/webpack4-ssr-config/favicon.ico
--------------------------------------------------------------------------------
/webpack3-basic-config/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zdliuccit/vue-webpack-config/HEAD/webpack3-basic-config/favicon.ico
--------------------------------------------------------------------------------
/webpack4-basic-config/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zdliuccit/vue-webpack-config/HEAD/webpack4-basic-config/favicon.ico
--------------------------------------------------------------------------------
/webpack4-ssr-config/dist/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zdliuccit/vue-webpack-config/HEAD/webpack4-ssr-config/dist/favicon.ico
--------------------------------------------------------------------------------
/webpack4-basic-config/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | 'autoprefixer': { browsers: '> 0.1%' },
4 | },
5 | }
6 |
--------------------------------------------------------------------------------
/webpack3-basic-config/doc/images/koa2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zdliuccit/vue-webpack-config/HEAD/webpack3-basic-config/doc/images/koa2.jpg
--------------------------------------------------------------------------------
/webpack3-basic-config/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zdliuccit/vue-webpack-config/HEAD/webpack3-basic-config/public/favicon.ico
--------------------------------------------------------------------------------
/react-base-webpack/constants.js:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | */
4 | module.exports = {
5 | proxy: {
6 | '/api': 'http://restapi.amap.com',
7 | },
8 | }
9 |
--------------------------------------------------------------------------------
/webpack/src/index.css:
--------------------------------------------------------------------------------
1 | html, body {
2 | position: absolute;
3 | width: 100%;
4 | height: 100%;
5 | display: flex;
6 | color: #3a8ee6
7 | }
8 |
--------------------------------------------------------------------------------
/webpack3-basic-config/doc/images/catalog.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zdliuccit/vue-webpack-config/HEAD/webpack3-basic-config/doc/images/catalog.png
--------------------------------------------------------------------------------
/webpack4-ssr-config/client/assets/images/01.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zdliuccit/vue-webpack-config/HEAD/webpack4-ssr-config/client/assets/images/01.jpg
--------------------------------------------------------------------------------
/webpack4-ssr-config/client/assets/images/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zdliuccit/vue-webpack-config/HEAD/webpack4-ssr-config/client/assets/images/logo.png
--------------------------------------------------------------------------------
/webpack/test/functions.test.js:
--------------------------------------------------------------------------------
1 | import functions from '../src/functions'
2 |
3 | test('sum(2 + 2) 等于 4', () => {
4 | expect(functions.sum(2, 2)).toBe(4)
5 | })
6 |
--------------------------------------------------------------------------------
/webpack3-basic-config/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | "env"
4 | ],
5 | "plugins": [
6 | "transform-vue-jsx",
7 | "syntax-dynamic-import"
8 | ]
9 | }
--------------------------------------------------------------------------------
/webpack3-basic-config/client/assets/images/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zdliuccit/vue-webpack-config/HEAD/webpack3-basic-config/client/assets/images/logo.png
--------------------------------------------------------------------------------
/webpack4-ssr-config/config/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by zdliu on 2018/7/6.
3 | * * app入口,使整个应用基于es6开发
4 | */
5 | require('@babel/polyfill')
6 | require('./koa.server')
7 |
--------------------------------------------------------------------------------
/react-base-webpack/config/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by zdliuccit on 2018/11/1.
3 | * * app入口,使整个应用基于es6开发
4 | */
5 | require('@babel/polyfill')
6 | require('./koa.server')
7 |
--------------------------------------------------------------------------------
/webpack4-basic-config/config/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by zdliuccit on 2017/9/6.
3 | * * app入口,使整个应用基于es6开发
4 | */
5 | require('@babel/polyfill')
6 | require('./koa-dev-server')
7 |
--------------------------------------------------------------------------------
/webpack/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | [
4 | "env",
5 | {
6 | "targets": {
7 | "node": "4"
8 | }
9 | }
10 | ]
11 | ]
12 | }
13 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | # dependencies
3 | **/node_modules
4 | # roadhog-api-doc ignore
5 | /src/utils/request-temp.js
6 | _roadhog-api-doc
7 |
8 | # production
9 | */.vscode
10 | .idea
11 | */.idea
12 |
--------------------------------------------------------------------------------
/koa-app/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | [
4 | "@babel/preset-env",
5 | {
6 | "targets": {
7 | "node": "current"
8 | }
9 | }
10 | ]
11 | ]
12 | }
13 |
--------------------------------------------------------------------------------
/react-base-webpack/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | 'autoprefixer': { browsers: '> 0.1%' },
4 | // 'postcss-pxtorem': { rootValue: 100, propWhiteList: [], replace: true, },
5 | },
6 | }
7 |
--------------------------------------------------------------------------------
/webpack4-ssr-config/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | 'autoprefixer': { browsers: '> 0.1%' },
4 | // 'postcss-pxtorem': { rootValue: 100, propWhiteList: [], replace: true, },
5 | },
6 | }
7 |
--------------------------------------------------------------------------------
/webpack4-ssr-config/constants.js:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | */
4 | module.exports = {
5 | proxy: {
6 | '/api': 'http://restapi.amap.com/',
7 | },
8 | prodProxy: {
9 | '/api': 'http://restapi.amap.com/',
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/webpack4-ssr-config/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | "@babel/preset-env"
4 | ],
5 | "plugins": [
6 | "transform-vue-jsx",
7 | "@babel/plugin-syntax-jsx",
8 | "@babel/plugin-syntax-dynamic-import"
9 | ]
10 | }
--------------------------------------------------------------------------------
/webpack3-basic-config/client/routes.js:
--------------------------------------------------------------------------------
1 | import main from './view/index.vue'
2 |
3 | const routes = [
4 | {
5 | path: '/',
6 | component: main,
7 | meta: { title: '首页' }
8 | },
9 | ]
10 |
11 | export default routes
12 |
--------------------------------------------------------------------------------
/webpack4-basic-config/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | "@babel/preset-env"
4 | ],
5 | "plugins": [
6 | "transform-vue-jsx",
7 | "@babel/plugin-syntax-jsx",
8 | "@babel/plugin-syntax-dynamic-import"
9 | ]
10 | }
11 |
--------------------------------------------------------------------------------
/react-base-webpack/client/view/login.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | class Login extends React.Component {
4 | render() {
5 | return (
6 |
7 | 登陆页面
8 |
9 | )
10 | }
11 | }
12 |
13 | export default Login
--------------------------------------------------------------------------------
/koa-app/app/controller/User.js:
--------------------------------------------------------------------------------
1 | class User {
2 |
3 | async login(ctx) {
4 | ctx.body = ''
5 | }
6 |
7 | async signOut(ctx) {
8 | }
9 |
10 | async register(ctx) {
11 | ctx.body = ''
12 | }
13 | }
14 |
15 | export default new User()
16 |
--------------------------------------------------------------------------------
/webpack4-basic-config/constants.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by liuzhengdong on 2017/7/6.
3 | */
4 | /**
5 | * 本文件仅用于本地开发环境,用于存放一些常量
6 | */
7 | module.exports = {
8 | // 代理
9 | proxy: {
10 | '/v3/assistant': 'http://restapi.amap.com/v3/',
11 | },
12 | }
13 |
--------------------------------------------------------------------------------
/webpack4-ssr-config/client/plugins/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import 'quill/dist/quill.core.css'
3 | import 'quill/dist/quill.snow.css'
4 | import 'quill/dist/quill.bubble.css'
5 |
6 | if (process.browser) {
7 | Vue.use(require('vue-quill-editor/dist/ssr'))
8 | }
--------------------------------------------------------------------------------
/webpack4-basic-config/src/routes.js:
--------------------------------------------------------------------------------
1 | import businessRoute from './views/business/routes'
2 | import empty from './app.vue'
3 |
4 | const routes = [
5 | {
6 | path: '/',
7 | component: empty,
8 | children: businessRoute
9 | },
10 | ]
11 |
12 | export default routes
13 |
--------------------------------------------------------------------------------
/webpack4-basic-config/src/store/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Vuex from 'vuex'
3 | import test from './modules/test'
4 |
5 | Vue.use(Vuex)
6 |
7 | export function createStore() {
8 | return new Vuex.Store({
9 | modules: {
10 | test
11 | }
12 | })
13 | }
14 |
--------------------------------------------------------------------------------
/webpack4-ssr-config/client/store/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Vuex from 'vuex'
3 | import test from './modules/test'
4 |
5 | Vue.use(Vuex)
6 |
7 | export function createStore() {
8 | return new Vuex.Store({
9 | modules: {
10 | test
11 | }
12 | })
13 | }
14 |
--------------------------------------------------------------------------------
/webpack3-basic-config/constants.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by liuzhengdong on 2017/7/6.
3 | */
4 | /**
5 | * 本文件仅用于本地开发环境,用于存放一些常量
6 | */
7 | module.exports = {
8 | // 登陆
9 | loginTargets: {
10 | dev: 'http://shop.dev.so:8080',
11 | test: 'http://shop.test.so:8080',
12 | },
13 | }
14 |
--------------------------------------------------------------------------------
/webpack4-ssr-config/client/views/test/routes.js:
--------------------------------------------------------------------------------
1 | const data = () => import('./data.vue')
2 | const ajax = () => import('./ajax.vue')
3 |
4 | export default [
5 | {
6 | path: 'data',
7 | component: data,
8 | },
9 | {
10 | path: 'ajax',
11 | component: ajax,
12 | }
13 | ]
14 |
--------------------------------------------------------------------------------
/webpack3-basic-config/config/utils/http/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 为vue实例添加http方法
3 | * Vue.use(http)
4 | */
5 | import http from './http'
6 |
7 | export default {
8 | /**
9 | * install钩子
10 | * @param {Vue} Vue Vue
11 | */
12 | install(Vue) {
13 | Vue.prototype.http = http
14 | },
15 | }
16 |
--------------------------------------------------------------------------------
/webpack4-basic-config/config/utils/http/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 为vue实例添加http方法
3 | * Vue.use(http)
4 | */
5 | import http from './http'
6 |
7 | export default {
8 | /**
9 | * install钩子
10 | * @param {Vue} Vue Vue
11 | */
12 | install(Vue) {
13 | Vue.prototype.http = http
14 | },
15 | }
16 |
--------------------------------------------------------------------------------
/koa-app/app/router/user.js:
--------------------------------------------------------------------------------
1 | import UserController from '../controller/User'
2 | import Router from 'koa-router'
3 |
4 | const User = new Router();
5 |
6 | User.get('/login', UserController.login);
7 | User.get('/signOut', UserController.signOut);
8 | User.get('/register', UserController.register);
9 |
10 | export default User
11 |
--------------------------------------------------------------------------------
/webpack3-basic-config/config/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by liuzhengdong on 2017/9/6.
3 | * * app入口,使整个应用基于es6开发
4 | */
5 | require('babel-core/register')
6 | require('babel-polyfill')
7 | if (process.env.NODE_ENV === 'development') {
8 | require('./koa-dev-server')
9 | } else {
10 | require('./koa-prod-server')
11 | }
12 |
--------------------------------------------------------------------------------
/webpack3-basic-config/server.config.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 配置服务端口,以及代理
3 | */
4 | const constants = require('./constants')
5 | const common = 'test'
6 | module.exports = {
7 | appPort: 9009,
8 | proxy: {
9 | '/api/test': constants.loginTargets[common],
10 | '/v3/assistant': 'http://restapi.amap.com/v3/',
11 | },
12 | }
13 |
--------------------------------------------------------------------------------
/koa-app/app/middleWares/static.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 设置静态资源请求目录和设置缓存
3 | * @return {Promise.}
4 | */
5 | import serverStatic from 'koa-static'
6 |
7 | const path = require('path')
8 |
9 | export default () => {
10 | return serverStatic(path.join(process.cwd(), 'app/public'), { maxAge: 60 * 60 * 24 * 30 * 1000, gzip: true })
11 | }
12 |
--------------------------------------------------------------------------------
/webpack4-ssr-config/config/http/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by zdliuccit on 2017/9/6.
3 | * 为vue实例添加http方法
4 | * Vue.use(http)
5 | */
6 | import http from './http'
7 |
8 | export default {
9 | /**
10 | * install钩子
11 | * @param {Vue} Vue Vue
12 | */
13 | install(Vue) {
14 | Vue.prototype.$http = http
15 | },
16 | }
17 |
--------------------------------------------------------------------------------
/webpack/test/loader.test.js:
--------------------------------------------------------------------------------
1 | import 'babel-polyfill'
2 | import compiler from './compiler.js';
3 |
4 | test('Inserts name and outputs JavaScript', async () => {
5 | const stats = await compiler('example.txt');
6 | const output = stats.toJson().modules[0].source;
7 |
8 | // expect(output).toBe('export default "Hey Alice!\\n"');
9 | });
10 |
--------------------------------------------------------------------------------
/webpack4-ssr-config/config/middle/staticMiddleWare.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 设置静态资源请求目录和设置缓存
3 | * @return {Promise.}
4 | */
5 | const path = require('path')
6 | const serverStatic = require("koa-static")
7 |
8 | module.exports = function () {
9 | return serverStatic(path.resolve(process.cwd()), { maxAge: 30 * 24 * 60 * 60 * 1000, gzip: true })
10 | }
--------------------------------------------------------------------------------
/webpack3-basic-config/config/utils/staticMiddleWare.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 设置静态资源请求目录和设置缓存
3 | * @return {Promise.}
4 | */
5 | const path = require('path')
6 | const serverStatic = require("koa-static")
7 |
8 | module.exports = function () {
9 | return serverStatic(path.join(process.cwd(), 'public'), { maxAge: 30 * 24 * 60 * 60 * 1000, gzip: true })
10 | }
--------------------------------------------------------------------------------
/webpack4-basic-config/config/utils/staticMiddleWare.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 设置静态资源请求目录和设置缓存
3 | * @return {Promise.}
4 | */
5 | const path = require('path')
6 | const serverStatic = require("koa-static")
7 |
8 | module.exports = function () {
9 | return serverStatic(path.join(process.cwd(), 'dist'), {maxAge: 30 * 24 * 60 * 60 * 1000, gzip: true})
10 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Webpack、Vue、React、Koa2
2 |
3 | ### React
4 |
5 | * [基于webpack4、koa2的react基础配置脚手架](react-base-webpack)
6 |
7 | ### Vue
8 |
9 | * [基于webpack3、koa2的vue的基础配置脚手架](webpack3-basic-config)
10 | * [基于webpack4、koa2的vue的基础配置脚手架](webpack4-basic-config)
11 | * [基于webpack4、koa2的vue的SSR配置脚手架](webpack4-ssr-config)
12 |
13 |
14 | ### Node
15 |
16 | * [koa服务端](koa-app)
17 |
--------------------------------------------------------------------------------
/react-base-webpack/config/middle/staticMiddleWare.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by zdliuccit on 2018/11/1.
3 | * 设置静态资源请求目录和设置缓存
4 | * @return {Promise.}
5 | */
6 | const path = require('path')
7 | const serverStatic = require("koa-static")
8 |
9 | module.exports = function () {
10 | return serverStatic(path.resolve(process.cwd()), { maxAge: 30 * 24 * 60 * 60 * 1000, gzip: true })
11 | }
--------------------------------------------------------------------------------
/webpack4-ssr-config/client/routes.js:
--------------------------------------------------------------------------------
1 | import testRoutes from './views/test/routes'
2 | import entry from './app.vue'
3 |
4 | const home = () => import('./views/home.vue')
5 | const routes = [
6 | {
7 | path: '/',
8 | component: home
9 | },
10 | {
11 | path: '/test',
12 | component: entry,
13 | children: testRoutes
14 | },
15 | ]
16 |
17 | export default routes
18 |
--------------------------------------------------------------------------------
/react-base-webpack/config/logger/koa-logger.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by zdliuccit on 2017/9/22.
3 | * log模块,依赖winston
4 | */
5 |
6 | const winston = require('winston')
7 |
8 | module.exports = function (filename) {
9 | return winston.loggers.get(filename, {
10 | console: {
11 | level: 'info', // 定死这个级别,只允许使用debug,warn,error三个方法
12 | colorize: true,
13 | label: filename,
14 | },
15 | })
16 | }
17 |
--------------------------------------------------------------------------------
/webpack4-ssr-config/config/logger/koa-logger.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by zdliuccit on 2017/9/22.
3 | * log模块,依赖winston
4 | */
5 |
6 | const winston = require('winston')
7 |
8 | module.exports = function (filename) {
9 | return winston.loggers.get(filename, {
10 | console: {
11 | level: 'info', // 定死这个级别,只允许使用debug,warn,error三个方法
12 | colorize: true,
13 | label: filename,
14 | },
15 | })
16 | }
17 |
--------------------------------------------------------------------------------
/webpack3-basic-config/config/utils/logger/koa-logger.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by liuzhengdong on 2017/9/22.
3 | * log模块,依赖winston
4 | */
5 |
6 | const winston = require('winston')
7 |
8 | module.exports = function (filename) {
9 | return winston.loggers.get(filename, {
10 | console: {
11 | level: 'info', // 定死这个级别,只允许使用debug,warn,error三个方法
12 | colorize: true,
13 | label: filename,
14 | },
15 | })
16 | }
17 |
--------------------------------------------------------------------------------
/webpack4-basic-config/config/utils/logger/koa-logger.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by liuzhengdong on 2017/9/22.
3 | * log模块,依赖winston
4 | */
5 |
6 | const winston = require('winston')
7 |
8 | module.exports = function (filename) {
9 | return winston.loggers.get(filename, {
10 | console: {
11 | level: 'info', // 定死这个级别,只允许使用debug,warn,error三个方法
12 | colorize: true,
13 | label: filename,
14 | },
15 | })
16 | }
17 |
--------------------------------------------------------------------------------
/webpack3-basic-config/client/index.js:
--------------------------------------------------------------------------------
1 | import 'babel-polyfill'
2 | // 引入响应式设计JS
3 | import '@config/utils/responsiveDesign'
4 | // 第三方库
5 | import Vue from 'vue'
6 | // reset样式
7 | import '@/assets/css/common.css'
8 | // vue config配置文件
9 | import './config'
10 | // 自己实现的方法
11 | import router from './router'
12 | import App from './app.vue'
13 |
14 | /*eslint-disable*/
15 | new Vue({
16 | el: '#app',
17 | router,
18 | // store,
19 | render: h => h(App)
20 | })
21 |
--------------------------------------------------------------------------------
/react-base-webpack/app.config.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 项目的一些定制化配置
3 | */
4 | const path = require('path')
5 | const constants = require('./constants')
6 |
7 | module.exports = {
8 | // 主服务启动端口
9 | appPort: 8088,
10 | // 代理配置,可支持多个代理,key为前缀,命中后,会把前缀去掉,转发到代理服务器
11 | proxy: constants.proxy,
12 | // webpack的差异化配置
13 | webpack: {
14 | entry: {
15 | app: path.join(__dirname, 'client/index.js') // 入口
16 | },
17 | },
18 | // 自定义中间件 async await函数写法
19 | middleWares: []
20 | }
21 |
--------------------------------------------------------------------------------
/koa-app/app/router/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块化处理router
3 | */
4 | import Router from 'koa-router'
5 | import User from './user'
6 |
7 | const router = new Router()
8 |
9 | /**
10 | * 启动路由
11 | * allowedMethods,在当所有路由中间件最后调用.此时根据 ctx.status 设置 response 响应头
12 | */
13 | export default (app) => {
14 | router.get('/', async ctx => {
15 | ctx.body = 'ml-app'
16 | })
17 | router.use('/user', User.routes(), User.allowedMethods())
18 | app.use(router.routes(), router.allowedMethods())
19 | }
20 |
--------------------------------------------------------------------------------
/koa-app/app.config.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 配置文件
3 | */
4 | export default {
5 | appPort: 7878,
6 | db: {
7 | url: 'mongodb://localhost:27017/ml',
8 | },
9 | secret: 'zdliuccit',
10 | /**
11 | * 限流中间件配置,令牌桶(Token bucket)
12 | * @desc 限流三种算法 令牌桶(Token bucket) 漏桶(Leaky bucket) 计数器(Counter)
13 | * enable # 状态
14 | * rate # 令牌桶模式 令牌加入桶的速率
15 | * upperLimit # 上限
16 | * */
17 | currentLimitedConfig: {
18 | enable: true,
19 | rate: 100,
20 | upperLimit: 1000
21 | },
22 | }
23 |
--------------------------------------------------------------------------------
/koa-app/app/middleWares/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @file 中间件集合
3 | */
4 | import staticMiddleWares from './static'
5 | import limitFlowMiddleWares from './limitFlow'
6 | import errorMiddleWare from './error'
7 |
8 | /**
9 | * 中间件,一组async函数,generator函数需要convert转换
10 | */
11 | export default (app) => {
12 | const middleWares = [
13 | errorMiddleWare,
14 | staticMiddleWares(),
15 | limitFlowMiddleWares()
16 | ]
17 | middleWares.forEach((middleware) => {
18 | app.use(middleware)
19 | })
20 | }
21 |
--------------------------------------------------------------------------------
/react-base-webpack/client/App.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import PrivateRoute from './components/privateRoute'
3 | import { Route, Switch } from 'react-router-dom'
4 | import Login from './view/login'
5 | import Index from './view/index'
6 |
7 | class App extends React.Component {
8 | render() {
9 | return (
10 |
11 |
12 |
13 |
14 | )
15 | }
16 | }
17 |
18 | export default App
19 |
--------------------------------------------------------------------------------
/webpack3-basic-config/config/utils/errorMiddleWare.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by liuzhengdong on 2017/9/7.
3 | * 错误处理中间件
4 | * @param {ctx} ctx koa ctx
5 | * @param {Function} next koa next */
6 |
7 | module.exports = async function (ctx, next) {
8 | try {
9 | // Node标识
10 | ctx.set('X-Proxy', 'Node Server')
11 | await next()
12 | } catch (err) {
13 | ctx.status = err.status || 500
14 | ctx.body = 'We are sorry. Internal server error occurred.'
15 | ctx.app.emit('error', err, ctx)
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/webpack4-basic-config/config/utils/errorMiddleWare.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by liuzhengdong on 2017/9/7.
3 | * 错误处理中间件
4 | * @param {ctx} ctx koa ctx
5 | * @param {Function} next koa next */
6 |
7 | module.exports = async function (ctx, next) {
8 | try {
9 | // Node标识
10 | ctx.set('X-Proxy', 'Node Server')
11 | await next()
12 | } catch (err) {
13 | ctx.status = err.status || 500
14 | ctx.body = 'We are sorry. Internal server error occurred.'
15 | ctx.app.emit('error', err, ctx)
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/webpack4-ssr-config/app.config.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 项目的一些定制化配置
3 | */
4 | const path = require('path')
5 | const constants = require('./constants')
6 | const isProd = process.env.NODE_ENV === 'production'
7 |
8 | module.exports = {
9 | // 主服务启动端口
10 | appPort: 8098,
11 | // 代理配置,可支持多个代理,key为前缀,命中后,会把前缀去掉,转发到代理服务器
12 | proxy: isProd ? constants.prodProxy : constants.proxy,
13 | // webpack的差异化配置
14 | webpack: {
15 | entry: {
16 | app: path.join(__dirname, 'client/index.js'), // 入口
17 | },
18 | },
19 | }
20 |
--------------------------------------------------------------------------------
/koa-app/app/middleWares/error.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by zdliuccit on 2017/9/7.
3 | * 错误处理中间件,放在所以中间价之前,就可以捕获它们所有的同步或者异步代码中抛出的异常
4 | * @param ctx koa ctx
5 | * @param next koa next */
6 |
7 | export default async (ctx, next) => {
8 | try {
9 | // Node标识
10 | ctx.set('X-Proxy', 'Node Server')
11 | await next()
12 | } catch (err) {
13 | console.log('err', err)
14 | ctx.status = err.status || 500
15 | ctx.body = 'We are sorry. Internal server error occurred.'
16 | ctx.app.emit('error', err, ctx)
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/webpack3-basic-config/config/utils/env.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by liuzhengdong on 2017/9/7.
3 | * 各种环境变量
4 | */
5 | module.exports = {
6 | // 是否服务端渲染模式
7 | IS_SSR: process.env.RENDER_MODE === 'server',
8 | // 是否开发环境
9 | IS_DEBUG: process.env.NODE_ENV === 'development',
10 | // 是否生产环境,不能根据process.env.NODE_ENV === 'production'来判断
11 | // 我们设置所有服务器集成部署方式都是process.env.NODE_ENV === 'production'
12 | // SERVER_ENV是与运维约定的一个环境变量,表示服务器环境,值可能为dev,test,pre,product
13 | IS_SERVER_PRODUCTION: process.env.SERVER_ENV === 'production',
14 | }
15 |
--------------------------------------------------------------------------------
/webpack4-basic-config/config/utils/env.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by liuzhengdong on 2017/9/7.
3 | * 各种环境变量
4 | */
5 | module.exports = {
6 | // 是否服务端渲染模式
7 | IS_SSR: process.env.RENDER_MODE === 'server',
8 | // 是否开发环境
9 | IS_DEBUG: process.env.NODE_ENV === 'development',
10 | // 是否生产环境,不能根据process.env.NODE_ENV === 'production'来判断
11 | // 我们设置所有服务器集成部署方式都是process.env.NODE_ENV === 'production'
12 | // SERVER_ENV是与运维约定的一个环境变量,表示服务器环境,值可能为dev,test,pre,product
13 | IS_SERVER_PRODUCTION: process.env.SERVER_ENV === 'production',
14 | }
15 |
--------------------------------------------------------------------------------
/react-base-webpack/client/components/privateRoute/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { Route, Redirect, } from 'react-router-dom'
3 | import { isAuthenticated } from './../../utils/Session'
4 |
5 | const PrivateRoute = ({ component: Component, ...rest }) => (
6 | (
7 | !!isAuthenticated()
8 | ?
9 | :
13 | )}/>
14 | )
15 |
16 | export default PrivateRoute
--------------------------------------------------------------------------------
/react-base-webpack/config/middle/errorMiddleWare.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by zdliuccit on 2018/11/1.
3 | * 错误处理中间件,放在所以中间价之前,就可以捕获它们所有的同步或者异步代码中抛出的异常
4 | * @param {ctx} ctx koa ctx
5 | * @param {Function} next koa next */
6 |
7 | module.exports = async function (ctx, next) {
8 | try {
9 | // Node标识
10 | ctx.set('X-Proxy', 'Node Server')
11 | await next()
12 | } catch (err) {
13 | ctx.status = err.status || 500
14 | ctx.body = 'We are sorry. Internal server error occurred.'
15 | ctx.app.emit('error', err, ctx)
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/webpack4-ssr-config/config/middle/errorMiddleWare.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by zdliuccit on 2017/9/7.
3 | * 错误处理中间件,放在所以中间价之前,就可以捕获它们所有的同步或者异步代码中抛出的异常
4 | * @param {ctx} ctx koa ctx
5 | * @param {Function} next koa next */
6 |
7 | module.exports = async function (ctx, next) {
8 | try {
9 | // Node标识
10 | ctx.set('X-Proxy', 'Node Server')
11 | await next()
12 | } catch (err) {
13 | ctx.status = err.status || 500
14 | ctx.body = 'We are sorry. Internal server error occurred.'
15 | ctx.app.emit('error', err, ctx)
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/react-base-webpack/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | "@babel/preset-env",
4 | "@babel/preset-react"
5 | ],
6 | "plugins": [
7 | "@babel/plugin-proposal-class-properties",
8 | [
9 | "import",
10 | {
11 | "libraryName": "antd",
12 | "libraryDirectory": "es",
13 | "style": "css"
14 | // `style: true` 会加载 less 文件
15 | }
16 | ]
17 | // ["@babel/plugin-proposal-decorators", { "legacy": true }],
18 | // ["@babel/plugin-proposal-class-properties", { "loose": true }],
19 | ]
20 | }
--------------------------------------------------------------------------------
/webpack4-basic-config/app.config.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 项目的一些定制化配置
3 | */
4 | const path = require('path')
5 | const constants = require('./constants')
6 |
7 | module.exports = {
8 | // 主服务启动端口
9 | appPort: 8686,
10 | // 代理配置,可支持多个代理,key为前缀,命中后,会把前缀去掉,转发到代理服务器
11 | proxy: constants.proxy,
12 | // 可以添加第三方包,加快打包速度和加载, webpack.DllPlugin
13 | webpackDLL: [],
14 | // webpack的差异化配置
15 | webpack: {
16 | entry: {
17 | app: path.join(__dirname, 'src/index.js'),
18 | },
19 | },
20 | // 自定义中间件 async await函数写法
21 | middleWares: []
22 | }
23 |
--------------------------------------------------------------------------------
/koa-app/pm2.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | apps: [{
3 | name: 'ml-app', // app名称
4 | script: 'app/index.js', // 要运行的脚本的路径。
5 | args: '', // 由传递给脚本的参数组成的字符串或字符串数组。
6 | output: './log/out.log',
7 | error: './log/error.log',
8 | log: './log/combined.outerr.log',
9 | merge_logs: true, // 集群的所有实例的日志文件合并
10 | log_date_format: "DD-MM-YYYY",
11 | instances: 4, // 进程数 1、数字 2、'max'根据cpu内核数
12 | max_memory_restart: '1G', // 当内存超过1024M时自动重启
13 | watching: true,
14 | env_production: {
15 | NODE_ENV: 'production'
16 | }
17 | }],
18 | }
19 |
--------------------------------------------------------------------------------
/react-base-webpack/client/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by zdliuccit on 18/11/1.
3 | */
4 | import '@babel/polyfill'
5 | import React from 'react'
6 | import ReactDOM from 'react-dom'
7 | import App from './App'
8 | import { BrowserRouter as Router } from 'react-router-dom'
9 | import { LocaleProvider } from 'antd'
10 | import zh_CN from 'antd/lib/locale-provider/zh_CN'
11 |
12 | ReactDOM.render(
13 |
14 |
15 |
16 |
17 | ,
18 | document.getElementById('app')
19 | )
20 |
21 | if (module.hot) {
22 | module.hot.accept()
23 | }
--------------------------------------------------------------------------------
/webpack4-ssr-config/client/router.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Router from 'vue-router'
3 | import routes from './routes'
4 |
5 | Vue.use(Router)
6 |
7 | export function createRouter() {
8 | const router = new Router({
9 | mode: 'history',
10 | fallback: false,
11 | // base: '/ssr',
12 | routes
13 | })
14 |
15 | router.beforeEach((to, from, next) => {
16 | /*todo
17 | * 做权限验证的时候,服务端和客户端状态同步的时候会执行一次
18 | * 建议vuex里用一个状态值控制,默认false,同步时直接next,因为服务端已经执行过。
19 | * */
20 | next()
21 | })
22 |
23 | router.afterEach((route) => {
24 | /*todo*/
25 | })
26 | return router
27 | }
--------------------------------------------------------------------------------
/koa-app/app/db/index.js:
--------------------------------------------------------------------------------
1 | import mongoose from 'mongoose'
2 | import UserModel from './../model/UserModel'
3 | import appConfig from './../../app.config'
4 |
5 | const NODE_ENV = process.env.NODE_ENV
6 |
7 | mongoose.connect(
8 | appConfig.db.url,
9 | {
10 | useNewUrlParser: true,
11 | bufferCommands: false,
12 | autoIndex: NODE_ENV === 'development'
13 | }
14 | );
15 |
16 | const db = mongoose.connection;
17 |
18 | db.on('error', console.error.bind(console, 'connection error:'));
19 | db.once('open', function () {
20 | console.log('db connect success');
21 | });
22 |
23 | export default {
24 | UserModel,
25 | }
26 |
--------------------------------------------------------------------------------
/webpack4-ssr-config/pm2.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | apps: [{
3 | name: 'ml-app', // app名称
4 | script: 'config/index.js', // 要运行的脚本的路径。
5 | args: '', // 由传递给脚本的参数组成的字符串或字符串数组。
6 | output: './log/out.log',
7 | error: './log/error.log',
8 | log: './log/combined.outerr.log',
9 | merge_logs: true, // 集群的所有实例的日志文件合并
10 | log_date_format: "DD-MM-YYYY",
11 | instances: 4, // 进程数 1、数字 2、'max'根据cpu内核数
12 | max_memory_restart: '1G', // 当内存超过1024M时自动重启
13 | watching: true,
14 | env_test: {
15 | NODE_ENV: 'production'
16 | },
17 | env_production: {
18 | NODE_ENV: 'production'
19 | }
20 | }],
21 | }
22 |
--------------------------------------------------------------------------------
/webpack4-ssr-config/client/utils/title.js:
--------------------------------------------------------------------------------
1 | function getTitle(vm) {
2 | const { title } = vm.$options
3 | if (title) {
4 | return typeof title === 'function' ? title.call(vm) : title
5 | }
6 | }
7 |
8 | /**
9 | * 生产环境 server处理
10 | */
11 | const serverTitleMixin = {
12 | created() {
13 | const title = getTitle(this)
14 | if (title) this.$ssrContext.title = title || 'Vue Koa2 SSR'
15 | }
16 | }
17 |
18 | /**
19 | * 开发环境 正常处理
20 | */
21 | const clientTitleMixin = {
22 | mounted() {
23 | const title = getTitle(this)
24 | if (title) document.title = title || 'Vue Koa2 SSR'
25 | }
26 | }
27 |
28 | export default process.env.VUE_ENV === 'server' ? serverTitleMixin : clientTitleMixin
29 |
--------------------------------------------------------------------------------
/webpack3-basic-config/config/utils/setCookieMiddleWare.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 生产环境屏蔽
3 | * 黑科技----手动在浏览器地址栏输入url,达到设置cookie的效果
4 | * 比如在页面上输入 http://192.168.144.64:8023/set-cookie?name=aaa&value=111
5 | * 将会写入key为aaa值为111的cookie到浏览器中
6 | * @param {Object} ctx koa ctx
7 | * @param {Function} next koa next
8 | * @return {Promise} promise
9 | */
10 | // eslint-disable-next-line consistent-return
11 | module.exports = async function (ctx, next) {
12 | if (ctx.path !== '/set-cookie') {
13 | return next()
14 | }
15 | const params = ctx.query
16 | ctx.set('Set-Cookie', `${params.name}=${params.value}; Path=/; HttpOnly`)
17 | ctx.body = `Cookie '${params.name}' has been successfully set to '${params.value}'!`
18 | }
19 |
--------------------------------------------------------------------------------
/webpack3-basic-config/config/postcss.conf.js:
--------------------------------------------------------------------------------
1 | const autoprefixer = require('autoprefixer')
2 | const pxtorem = require('postcss-pxtorem')
3 | const webpackAppConfig = require('./../app.config').webpack
4 | /**
5 | * postcss 添加浏览器前缀插件
6 | * @return []
7 | */
8 | module.exports = function () {
9 | const posts = [
10 | // 添加浏览器前缀 解决兼容问题
11 | autoprefixer({ browsers: webpackAppConfig.browsers || '> 0.1%', }),
12 | ]
13 | // 是否对样式启用px到rem的转换, 默认不开启
14 | if (webpackAppConfig.enablePx2Rem) {
15 | const pxtoremOptions = Object.assign({}, {
16 | rootValue: 100,
17 | propWhiteList: [],
18 | replace: true,
19 | })
20 | posts.push(pxtorem(pxtoremOptions))
21 | }
22 | // 合并项目设置的插件
23 | return posts.concat(webpackAppConfig.postcss || [])
24 | }
25 |
--------------------------------------------------------------------------------
/koa-app/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ml",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "app/index.js",
6 | "scripts": {
7 | "start": "nodemon app/index.js",
8 | "test": "echo \"Error: no test specified\" && exit 1",
9 | "app": "pm2 start pm2.config.js --env production"
10 | },
11 | "author": "",
12 | "license": "ISC",
13 | "dependencies": {
14 | "@babel/core": "7.11.5",
15 | "@babel/preset-env": "7.11.5",
16 | "@babel/register": "7.11.5",
17 | "axios": "0.20.0",
18 | "keygrip": "1.1.0",
19 | "koa": "2.13.0",
20 | "koa-compress": "5.0.1",
21 | "koa-logger": "3.2.1",
22 | "koa-router": "9.4.0",
23 | "koa-session": "6.0.0",
24 | "koa-static": "5.0.0",
25 | "mongoose": "5.10.4",
26 | "nodemon": "2.0.4"
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/webpack4-basic-config/config/webpack.config.dll.js:
--------------------------------------------------------------------------------
1 | /**
2 | * webpack dll 配置 分离第三方库 加速打包和 有利于缓存
3 | * Created by liuzhengdong on 2018/4/12.
4 | */
5 | const webpack = require('webpack');
6 | const path = require('path');
7 | const appConfig = require(path.join(process.cwd(), 'app.config'))
8 |
9 | const vendors = ['vue', 'vuex', 'vue-router'];
10 | module.exports = {
11 | mode: 'production',
12 | output: {
13 | filename: '[name]_[chunkhash:8].dll.js',
14 | library: '[name]_[chunkhash:8]',
15 | },
16 | entry: {
17 | 'vendors': vendors.concat(appConfig.webpackDLL || []),
18 | },
19 | plugins: [
20 | new webpack.DllPlugin({
21 | name: '[name]_[chunkhash:8]',
22 | context: path.join(process.cwd()),
23 | path: path.join(process.cwd(), '[name]-manifest.json'),
24 | }),
25 | ],
26 | };
27 |
--------------------------------------------------------------------------------
/webpack4-ssr-config/client/index.js:
--------------------------------------------------------------------------------
1 | import '@babel/polyfill'
2 | import Vue from 'vue'
3 | import App from './app.vue'
4 | import { createStore } from './store'
5 | import { createRouter } from './router'
6 | import { sync } from 'vuex-router-sync'
7 |
8 | // reset 样式
9 | import './assets/css/reset.css'
10 |
11 | // config配置文件
12 | import './config'
13 | // 涉及到原生对象调用的插件统一放plugins目录下
14 | import './plugins'
15 | // 导出一个工厂函数,用于创建新的
16 | // 应用程序、router 和 store 实例
17 | export function createApp() {
18 | // 创建 router 实例
19 | const router = createRouter()
20 | // 创建 store 实力
21 | const store = createStore()
22 |
23 | // sync the router with the vuex store.
24 | sync(store, router)
25 |
26 | const app = new Vue({
27 | // 注入 router 到根 Vue 实例
28 | router,
29 | store,
30 | render: h => h(App)
31 | })
32 | return { app, router, store }
33 | }
--------------------------------------------------------------------------------
/webpack3-basic-config/app.config.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 项目的一些定制化配置
3 | */
4 | const path = require('path')
5 | const serverConfig = require('./server.config')
6 |
7 | module.exports = {
8 | // 主服务启动端口
9 | appPort: serverConfig.appPort,
10 | // 代理配置,可支持多个代理,key为前缀,命中后,会把前缀去掉,转发到代理服务器
11 | proxy: serverConfig.proxy,
12 | // webpack的差异化配置
13 | webpack: {
14 | entry: {
15 | app: path.join(__dirname, 'client/index.js'), // 入口
16 | vendor: ['vue', 'vue-router'] // 拆分框架代码
17 | },
18 | // 是否对样式启用px到rem的转换,配合config/utils/responsive-design.js适配移动端开发, 默认不开启
19 | enablePx2Rem: false,
20 | // 自定义Alias设置
21 | resolveAlias: {},
22 | // 扩展rules
23 | rules: [],
24 | // 扩展css postcss
25 | postcss: [],
26 | // 定义 autoprefixer 兼容 默认内部配置为 >0.1%
27 | browsers: ''
28 | },
29 | // 自定义中间件 async await函数写法
30 | middleWares: []
31 | }
32 |
--------------------------------------------------------------------------------
/webpack3-basic-config/config/utils/StringUtils.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by liuzhengdong on 2017/9/22.
3 | * 存放公共方法
4 | */
5 | module.exports = {
6 | /**
7 | * 函数节流
8 | * @param fn 函数
9 | * @param delay 多久执行一次
10 | * @param mustRunDelay 执行时间间隔
11 | * @return {Function}
12 | */
13 | throttle: function (fn, delay, mustRunDelay) {
14 | let timer = null
15 | let t_start
16 | return function () {
17 | let context = this, args = arguments, t_curr = +new Date()
18 | clearTimeout(timer)
19 | if (!t_start) {
20 | t_start = t_curr
21 | }
22 | if (t_curr - t_start >= mustRunDelay) {
23 | fn.apply(context, args)
24 | t_start = t_curr
25 | }
26 | else {
27 | timer = setTimeout(function () {
28 | fn.apply(context, args)
29 | }, delay)
30 | }
31 | }
32 | }
33 | }
--------------------------------------------------------------------------------
/webpack4-basic-config/config/utils/StringUtils.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by liuzhengdong on 2017/9/22.
3 | * 存放公共方法
4 | */
5 | module.exports = {
6 | /**
7 | * 函数节流
8 | * @param fn 函数
9 | * @param delay 多久执行一次
10 | * @param mustRunDelay 执行时间间隔
11 | * @return {Function}
12 | */
13 | throttle: function (fn, delay, mustRunDelay) {
14 | let timer = null
15 | let t_start
16 | return function () {
17 | let context = this, args = arguments, t_curr = +new Date()
18 | clearTimeout(timer)
19 | if (!t_start) {
20 | t_start = t_curr
21 | }
22 | if (t_curr - t_start >= mustRunDelay) {
23 | fn.apply(context, args)
24 | t_start = t_curr
25 | }
26 | else {
27 | timer = setTimeout(function () {
28 | fn.apply(context, args)
29 | }, delay)
30 | }
31 | }
32 | }
33 | }
--------------------------------------------------------------------------------
/webpack4-basic-config/vendors-manifest.json:
--------------------------------------------------------------------------------
1 | {"name":"vendors_e100c0e8","content":{"./node_modules/webpack/buildin/global.js":{"id":0,"buildMeta":{"providedExports":true}},"./node_modules/vue/dist/vue.runtime.esm.js":{"id":2,"buildMeta":{"exportsType":"namespace","providedExports":["default"]}},"./node_modules/timers-browserify/main.js":{"id":3,"buildMeta":{"providedExports":true}},"./node_modules/setimmediate/setImmediate.js":{"id":4,"buildMeta":{"providedExports":true}},"./node_modules/process/browser.js":{"id":5,"buildMeta":{"providedExports":true}},"./node_modules/vuex/dist/vuex.esm.js":{"id":6,"buildMeta":{"exportsType":"namespace","providedExports":["Store","install","mapState","mapMutations","mapGetters","mapActions","createNamespacedHelpers","default"]}},"./node_modules/vue-router/dist/vue-router.esm.js":{"id":7,"buildMeta":{"exportsType":"namespace","providedExports":["default"]}}}}
--------------------------------------------------------------------------------
/webpack4-ssr-config/config/webpack.client.config.js:
--------------------------------------------------------------------------------
1 | /**
2 | * webpack client配置
3 | * Created by zdliuccit on 2018/7/6.
4 | */
5 | const webpack = require('webpack')
6 | const merge = require('webpack-merge')
7 | const path = require('path')
8 | const baseConfig = require('./webpack.base.config')()
9 | const isProd = process.env.NODE_ENV === 'production'
10 |
11 | const VueSSRClientPlugin = require('vue-server-renderer/client-plugin')
12 | const config = merge(baseConfig, {
13 | entry: {
14 | app: path.join(process.cwd(), 'client/entry-client.js'),
15 | },
16 | mode: isProd ? 'production' : 'development',
17 | plugins: [
18 | new webpack.DefinePlugin({
19 | 'process.env.NODE_ENV': JSON.stringify(isProd ? 'production' : 'development'),
20 | 'process.env.VUE_ENV': '"client"'
21 | }),
22 | new VueSSRClientPlugin()
23 | ]
24 | })
25 |
26 | module.exports = config
27 |
--------------------------------------------------------------------------------
/webpack3-basic-config/config/utils/responsiveDesign.js:
--------------------------------------------------------------------------------
1 | /**
2 | * rem响应式方案的实现
3 | * 启用px到rem的转换enablePx2Rem配置项才会执行
4 | */
5 | import { throttle } from './StringUtils'
6 | const enablePx2Rem = require('./../../app.config').webpack.enablePx2Rem
7 | if (enablePx2Rem) {
8 | const win = global
9 | const doc = win.document
10 | const baseWidth = 750
11 | const documentHTML = doc.documentElement
12 | let pixelRatio = 2
13 |
14 | /**
15 | * 设置html根字体
16 | */
17 | function setRootFont () {
18 | const docWidth = documentHTML.getBoundingClientRect().width
19 | const scale = docWidth / baseWidth
20 | documentHTML.style.fontSize = `${scale * 100}px`
21 | pixelRatio = global.devicePixelRatio === 3 ? 3 : 2
22 | documentHTML.setAttribute('data-dpr', pixelRatio)
23 | }
24 |
25 | setRootFont()
26 | win.addEventListener('resize', throttle(setRootFont, 90, 100), false)
27 | }
28 |
29 |
--------------------------------------------------------------------------------
/webpack4-basic-config/config/utils/responsiveDesign.js:
--------------------------------------------------------------------------------
1 | /**
2 | * rem响应式方案的实现
3 | * 启用px到rem的转换enablePx2Rem配置项才会执行
4 | */
5 | import { throttle } from './StringUtils'
6 | const enablePx2Rem = require('./../../app.config').webpack.enablePx2Rem
7 | if (enablePx2Rem) {
8 | const win = global
9 | const doc = win.document
10 | const baseWidth = 750
11 | const documentHTML = doc.documentElement
12 | let pixelRatio = 2
13 |
14 | /**
15 | * 设置html根字体
16 | */
17 | function setRootFont () {
18 | const docWidth = documentHTML.getBoundingClientRect().width
19 | const scale = docWidth / baseWidth
20 | documentHTML.style.fontSize = `${scale * 100}px`
21 | pixelRatio = global.devicePixelRatio === 3 ? 3 : 2
22 | documentHTML.setAttribute('data-dpr', pixelRatio)
23 | }
24 |
25 | setRootFont()
26 | win.addEventListener('resize', throttle(setRootFont, 90, 100), false)
27 | }
28 |
29 |
--------------------------------------------------------------------------------
/react-base-webpack/config/http/http.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by zdliuccit on 2017/9/6.
3 | * http
4 | * addRequestInterceptor
5 | * addResponseInterceptor
6 | */
7 | import axios from 'axios'
8 |
9 | const defaultHeaders = {
10 | Accept: 'application/json, text/plain, */*; charset=utf-8',
11 | 'Content-Type': 'application/json; charset=utf-8',
12 | Pragma: 'no-cache',
13 | 'Cache-Control': 'no-cache',
14 | }
15 | // 设置默认头
16 | Object.assign(axios.defaults.headers.common, defaultHeaders)
17 |
18 | const methods = ['get', 'post', 'put', 'delete']
19 |
20 | const http = {}
21 | methods.forEach(method => {
22 | http[method] = axios[method].bind(axios)
23 | })
24 |
25 | export default http
26 |
27 | export const addRequestInterceptor =
28 | axios.interceptors.request.use.bind(axios.interceptors.request)
29 |
30 | export const addResponseInterceptor =
31 | axios.interceptors.response.use.bind(axios.interceptors.response)
32 |
--------------------------------------------------------------------------------
/webpack3-basic-config/config/utils/http/http.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by liuzhengdong on 2017/9/6.
3 | * http
4 | * addRequestInterceptor
5 | * addResponseInterceptor
6 | */
7 | import axios from 'axios'
8 |
9 | const defaultHeaders = {
10 | Accept: 'application/json, text/plain, */*; charset=utf-8',
11 | 'Content-Type': 'application/json; charset=utf-8',
12 | Pragma: 'no-cache',
13 | 'Cache-Control': 'no-cache',
14 | }
15 | // 设置默认头
16 | Object.assign(axios.defaults.headers.common, defaultHeaders)
17 |
18 | const methods = ['get', 'post', 'put', 'delete']
19 |
20 | const http = {}
21 | methods.forEach(method => {
22 | http[method] = axios[method].bind(axios)
23 | })
24 |
25 | export default http
26 |
27 | export const addRequestInterceptor =
28 | axios.interceptors.request.use.bind(axios.interceptors.request)
29 |
30 | export const addResponseInterceptor =
31 | axios.interceptors.response.use.bind(axios.interceptors.response)
32 |
--------------------------------------------------------------------------------
/webpack4-basic-config/config/utils/http/http.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by liuzhengdong on 2017/9/6.
3 | * http
4 | * addRequestInterceptor
5 | * addResponseInterceptor
6 | */
7 | import axios from 'axios'
8 |
9 | const defaultHeaders = {
10 | Accept: 'application/json, text/plain, */*; charset=utf-8',
11 | 'Content-Type': 'application/json; charset=utf-8',
12 | Pragma: 'no-cache',
13 | 'Cache-Control': 'no-cache',
14 | }
15 | // 设置默认头
16 | Object.assign(axios.defaults.headers.common, defaultHeaders)
17 |
18 | const methods = ['get', 'post', 'put', 'delete']
19 |
20 | const http = {}
21 | methods.forEach(method => {
22 | http[method] = axios[method].bind(axios)
23 | })
24 |
25 | export default http
26 |
27 | export const addRequestInterceptor =
28 | axios.interceptors.request.use.bind(axios.interceptors.request)
29 |
30 | export const addResponseInterceptor =
31 | axios.interceptors.response.use.bind(axios.interceptors.response)
32 |
--------------------------------------------------------------------------------
/webpack4-basic-config/src/store/modules/test.js:
--------------------------------------------------------------------------------
1 | const state = {
2 | count: 0
3 | }
4 |
5 | const getters = {
6 | getCount: state => state.count
7 | }
8 |
9 | const mutations = {
10 | INCREMENT: (state) => {
11 | state.count++
12 | },
13 | DECREMENT: (state) => {
14 | state.count--
15 | },
16 | INITCOUNT: (state, COUNT) => {
17 | state.count = COUNT
18 | }
19 | }
20 |
21 | const actions = {
22 | increment({state, commit}) {
23 | commit('INCREMENT')
24 | },
25 | decrement({state, commit}) {
26 | commit('DECREMENT')
27 | },
28 | loading({commit}) {
29 | return new Promise(resolve => {
30 | setTimeout(() => {
31 | resolve()
32 | }, 1000)
33 | }).then(() => {
34 | commit('INITCOUNT', 67)
35 | })
36 | },
37 | resetCount({commit}) {
38 | commit('INITCOUNT', 67)
39 | }
40 | }
41 |
42 | export default {
43 | state,
44 | getters,
45 | mutations,
46 | actions
47 | }
48 |
--------------------------------------------------------------------------------
/webpack4-basic-config/src/views/business/bus-detial.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
活动名称
6 |
{{coupon.name}}
7 |
8 |
9 |
活动时间
10 |
{{coupon.startDate}} - {{coupon.endDate}}
11 |
12 |
13 |
14 |
15 |
活动名称
16 |
{{coupon.name}}
17 |
18 |
19 |
活动时间
20 |
{{coupon.startDate}} - {{coupon.endDate}}
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/webpack/test/compiler.js:
--------------------------------------------------------------------------------
1 | import 'babel-polyfill'
2 | import path from 'path'
3 | import webpack from 'webpack'
4 | import memoryfs from 'memory-fs'
5 |
6 | function resolve(dir) {
7 | return path.resolve(process.cwd(), dir)
8 | }
9 |
10 | export default (fixture, options = {}) => {
11 | const compiler = webpack({
12 | context: __dirname,
13 | entry: `./${fixture}`,
14 | output: {
15 | path: path.resolve(__dirname),
16 | filename: 'bundle.js',
17 | },
18 | module: {
19 | rules: [{
20 | test: /\.txt$/,
21 | use: {
22 | loader: resolve('loaders/ml-loader.js'),
23 | options: {
24 | name: 'Alice'
25 | }
26 | }
27 | }]
28 | }
29 | })
30 | compiler.outputFileSystem = new memoryfs()
31 | return new Promise((resolve, reject) => {
32 | compiler.run((err, stats) => {
33 | if (err) reject(err)
34 | resolve(stats)
35 | })
36 | })
37 | }
38 |
--------------------------------------------------------------------------------
/koa-app/README.md:
--------------------------------------------------------------------------------
1 | # Koa服务
2 |
3 | ## Package 说明
4 | * koa # 主程
5 | * koa-router # 路由
6 | * koa-compress # 压缩响应
7 | * koa-logger # 日志
8 | * koa-session # session
9 | * koa-static # 静态资源服务
10 | * keygrip # 加密
11 | * @babel/core # 支持es6语法
12 | * @babel/preset-env # 支持es6语法
13 | * @babel/register # 支持es6语法
14 | * axios # http请求
15 | * mongoose # Mongoose是设计用于异步环境的MongoDB对象建模工具
16 | * nodemon # nodemon是一种工具,可在检测到目录中的文件更改时通过自动重新启动节点应用程序来帮助开发基于node.js的应用程序
17 |
18 | ## 目录
19 | ``` bash
20 | ├── app # Node代码目录
21 | │ ├── db # mangodb数据库操作
22 | │ │ ├── #
23 | │ │ └── #
24 | │ ├── middleWares # koa中间件
25 | │ ├── middle # koa2中间件目录
26 | │ └── router # koa路由封装
27 | ├── log # pm2日志输出目录
28 | ├── node_modules # node包
29 | ├── .gitignore # git配置
30 | ├── app.config.js # app配置文件
31 | ├── package.json #
32 | ├── package-lock.json #
33 | ├── pm2.config.js # 项目pm2配置
34 | ├── pm2.md # pm2的api文档
35 | ├── postcss.config.js # postcss配置文件
36 | └── README.md # 文档
37 | ```
38 |
--------------------------------------------------------------------------------
/react-base-webpack/index.template.ejs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | React Demo
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/webpack3-basic-config/index.template.ejs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | <%= htmlWebpackPlugin.options.gaScripts %>
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/webpack4-basic-config/config/webpack.config.dev.js:
--------------------------------------------------------------------------------
1 | /**
2 | * webpack client配置
3 | * Created by zdliuccit on 2018/7/6.
4 | */
5 | const webpack = require('webpack')
6 | const merge = require('webpack-merge')
7 | const base = require('./webpack.config.base')()
8 | const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
9 | const config = merge(base, {
10 | devtool: '#cheap-module-source-map',
11 | mode: 'development',
12 | plugins: [
13 | new webpack.DefinePlugin({
14 | 'process.env': {
15 | NODE_ENV: JSON.stringify("development"),
16 | },
17 | }),
18 | // 全局开启代码热替换
19 | new webpack.NamedModulesPlugin(),
20 | new webpack.HotModuleReplacementPlugin(),
21 | new FriendlyErrorsPlugin(),
22 | ]
23 | })
24 | Object.keys(config.entry).forEach(function (name) {
25 | config.entry[name] = ['webpack-hot-middleware/client?path=/__webpack_hmr&timeout=2000&reload=true'].concat(config.entry[name])
26 | })
27 |
28 | module.exports = config
29 |
--------------------------------------------------------------------------------
/webpack4-ssr-config/index.template.ejs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{title}}
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/webpack4-basic-config/src/router.js:
--------------------------------------------------------------------------------
1 | /* loading */
2 | import VueRouter from 'vue-router'
3 | import routes from './routes'
4 |
5 | const ProgressBar = require('progressbar.js')
6 |
7 | const router = new VueRouter({
8 | mode: 'history',
9 | routes
10 | })
11 |
12 | const doc = global.document
13 |
14 | // 响应式 SVG 进度条
15 | let line = null
16 |
17 | router.beforeEach((to, from, next) => {
18 | // 进度条开始
19 | if (line) { line.destroy() }
20 | line = new ProgressBar.Line('body', {
21 | color: '#009ce5',
22 | strokeWidth: 0.2,
23 | svgStyle: {position: 'fixed', zIndex: '10001', top: 0, left: 0, right: 0, maxHeight: '2px'}
24 | })
25 | line.animate(0.8, {duration: 500})
26 | next()
27 | })
28 |
29 | router.afterEach((route) => {
30 | // 设置标题
31 | doc.title = route.meta.title || '首页'
32 | // 进度条结束
33 | if (line) {
34 | line.animate(1, {duration: 1000}, () => {
35 | line.destroy()
36 | line = null
37 | })
38 | }
39 | })
40 |
41 | export default router
42 |
--------------------------------------------------------------------------------
/koa-app/app/middleWares/limitFlow.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @file limitFlow Node服务限制流量处理中间件
3 | * @desc 业务代码中的逻辑限流
4 | * @desc 常见的限流算法有:计数器、令牌桶、漏桶。这些都属于单机限流的范畴
5 | * @desc 另外为了限制某个资源被每个用户或者商户的访问次数,5s只能访问2次,或者一天只能调用1000次。这种需求,单机限流是无法实现的,这时就需要通过集群限流进行实现。
6 | * 如何实现?为了控制访问次数,肯定需要一个计数器,而且这个计数器只能保存在第三方服务,比如redis。
7 | */
8 | import appConfig from './../../app.config'
9 |
10 | const { enable, upperLimit, rate } = appConfig.currentLimitedConfig
11 |
12 | export default () => {
13 | let bucket = 0
14 | const callback = () => {
15 | setTimeout(() => {
16 | if (bucket < upperLimit) {
17 | bucket += 1
18 | }
19 | callback()
20 | }, 1000 / rate)
21 | }
22 | callback()
23 | return async (ctx, next) => {
24 | // console.log('当前Token bucket ', bucket)
25 | if (enable && bucket <= 0) {
26 | console.log('Token bucket 耗尽,开启限流')
27 | return ctx.body = { data: null, status: false, message: '亲~人太多,被挤爆了!' }
28 | }
29 | bucket -= 1;
30 | await next()
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/webpack3-basic-config/client/config.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import VueRouter from 'vue-router'
3 | // 引入http请求插件
4 | import http from '@config/utils/http'
5 | // 引入log日志插件
6 | import vueLogger from '@config/utils/logger/vue-logger'
7 | import { addRequestInterceptor, addResponseInterceptor } from '@config/utils/http/http'
8 |
9 | // 注册插件
10 | Vue.use(http)
11 | Vue.use(vueLogger)
12 | Vue.use(VueRouter)
13 |
14 | // request前自动添加api配置
15 | addRequestInterceptor(
16 | (config) => {
17 | // config.url = `/api${config.url}`
18 | return config
19 | },
20 | (error) => {
21 | return Promise.reject(error)
22 | }
23 | )
24 |
25 | // 返回response前处理
26 | addResponseInterceptor(
27 | (response) => {
28 | // 在这里统一前置处理请求响应
29 | if (Number(response.status) !== 200) {
30 | // 全局notify有问题,还是自己处理吧
31 | return Promise.reject(response.data)
32 | }
33 | return Promise.resolve(response.data)
34 | },
35 | (error) => {
36 | return Promise.reject(error || '出错了')
37 | }
38 | )
39 |
--------------------------------------------------------------------------------
/koa-app/app/app.js:
--------------------------------------------------------------------------------
1 | import Koa from 'koa'
2 | import Logger from 'koa-logger'
3 | import Compress from 'koa-compress'
4 | import Session from 'koa-session'
5 | import KeyGrip from 'keygrip'
6 | import appConfig from './../app.config'
7 | import middles from './middleWares'
8 | import router from './router'
9 |
10 | const app = new Koa()
11 | /** 设置签名cookie密钥。*/
12 | app.keys = new KeyGrip(['zdliuccit', 'ml', 'app'], 'sha256');
13 |
14 | /** session设置 */
15 | const SESSION_CONFIG = {
16 | key: 'ml-app', /** cookie键 */
17 | maxAge: 60 * 60 * 24 * 1000, /** session过期时间 */
18 | renew: false, /** 当会话即将过期时续订会话,因此我们可以始终保持用户登录。*/
19 | };
20 | app.use(Session(SESSION_CONFIG, app));
21 | app.use(Logger())
22 | app.use(Compress())
23 |
24 | /**
25 | * 启动自定义中间件
26 | */
27 | middles(app)
28 |
29 | /**
30 | * 启动路由
31 | */
32 | router(app)
33 |
34 | /**
35 | * app错误监听
36 | */
37 | app.on('error', (err) => {
38 | console.error('Server error: \n%s\n%s ', err.stack || '')
39 | })
40 |
41 | app.listen(appConfig.appPort)
42 |
--------------------------------------------------------------------------------
/react-base-webpack/client/view/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { Layout } from 'antd'
3 |
4 | const { Sider, Header, Content, Footer } = Layout
5 |
6 | class Index extends React.Component {
7 | state = {
8 | collapsed: false
9 | }
10 | toggle = () => {
11 | this.setState({
12 | collapsed: !this.state.collapsed
13 | })
14 | }
15 |
16 | render() {
17 | // 设置Sider的minHeight可以使左右自适应对齐
18 | return (
19 |
20 |
21 |
22 |
23 |
24 |
26 |
27 |
28 |
30 |
31 |
32 |
33 | )
34 | }
35 | }
36 |
37 | export default Index
--------------------------------------------------------------------------------
/webpack4-basic-config/src/index.js:
--------------------------------------------------------------------------------
1 | import '@babel/polyfill'
2 | import Vue from 'vue'
3 | import './config'
4 | import router from './router'
5 | import App from './app.vue'
6 | import vueStorage from './utils/storage'
7 |
8 | /**
9 | * @param {Object} Vue Vue
10 | * @param {router} [router=undefined] VueRouter 实例化对象
11 | * @param [] 路由白名单
12 | * @param (storage) => {} 回调函数
13 | */
14 | const store = vueStorage(Vue, router, [], (storage, to, from) => {
15 | return new Promise((resolve) => {
16 | // const { whether } = storage.getItem('userObject', false) || JSON.parse(localStorage.getItem('userObject')) || {}
17 | // if (!whether && to.path !== '/login') {
18 | // global.location.href = '/login'
19 | // } else {
20 | // storage.setItem('userObject', JSON.parse(localStorage.getItem('userObject')), false)
21 | resolve(storage, to, from)
22 | // }
23 | })
24 | })
25 |
26 | /*eslint-disable*/
27 | new Vue({
28 | el: '#app',
29 | router,
30 | store,
31 | render: h => h(App)
32 | })
33 |
--------------------------------------------------------------------------------
/webpack4-basic-config/index.template.ejs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/webpack/loaders/ml-loader.js:
--------------------------------------------------------------------------------
1 | const loaderUtils = require('loader-utils')
2 | const validateOptions = require('schema-utils')
3 | const fs = require('fs')
4 | const path = require('path')
5 | const schema = {
6 | type: 'object',
7 | properties: {
8 | test: {
9 | type: 'string'
10 | }
11 | }
12 | }
13 | module.exports = function (source) {
14 | const options = loaderUtils.getOptions(this)
15 | const callback = this.async()
16 | const msPath = path.resolve('loaders/ms.js')
17 |
18 | this.addDependency(msPath)
19 | console.log('options', options)
20 | validateOptions(schema, options, 'Example Loader')
21 |
22 | fs.readFile(msPath, 'utf-8', function (err, header) {
23 | if (err) return callback(err)
24 | callback(null, header + "\n" + source);
25 | })
26 | // return source
27 | }
28 |
29 | module.exports = function (source) {
30 | const options = loaderUtils.getOptions(this)
31 | source = source.replace(/\[name\]/g, options.name)
32 | return `export default ${JSON.stringify(source)}`
33 | }
34 |
--------------------------------------------------------------------------------
/webpack4-basic-config/src/views/business/routes.js:
--------------------------------------------------------------------------------
1 | import businessList from './business-list.vue'
2 | import businessDetail from './bus-detial.vue'
3 | import businessAddEdit from './bus-add-edit.vue'
4 |
5 | const routes = [
6 | {
7 | path: '/',
8 | name: 'businessList',
9 | component: businessList,
10 | meta: {
11 | title: '商家列表',
12 | sidebarLink: '/business/list'
13 | },
14 | },
15 | {
16 | path: 'add',
17 | name: 'businessAdd',
18 | component: businessAddEdit,
19 | meta: {
20 | title: '添加商家',
21 | sidebarLink: '/business/list'
22 | },
23 | },
24 | {
25 | path: 'edit/:id',
26 | name: 'businessEdit',
27 | component: businessAddEdit,
28 | meta: {
29 | title: '修改商家',
30 | sidebarLink: '/business/list'
31 | },
32 | },
33 | {
34 | path: 'detail/:id',
35 | name: 'businessDetail',
36 | component: businessDetail,
37 | meta: {
38 | title: '商家详情',
39 | sidebarLink: '/business/list'
40 | },
41 | },
42 | ]
43 |
44 | export default routes
45 |
--------------------------------------------------------------------------------
/react-base-webpack/client/utils/Session.js:
--------------------------------------------------------------------------------
1 | const LOGIN_COOKIE_NAME = 'sessionId'
2 |
3 | export function isAuthenticated() {
4 | return _getCookie(LOGIN_COOKIE_NAME)
5 | }
6 |
7 | export function authenticateSuccess(token) {
8 | _setCookie(LOGIN_COOKIE_NAME, token)
9 | }
10 |
11 | export function logout() {
12 | _setCookie(LOGIN_COOKIE_NAME, '', 0)
13 | }
14 |
15 | function _getCookie(name) {
16 | let start, end
17 | if (document.cookie.length > 0) {
18 | start = document.cookie.indexOf(name + '=')
19 | if (start !== -1) {
20 | start = start + name.length + 1
21 | end = document.cookie.indexOf(';', start)
22 | if (end === -1) {
23 | end = document.cookie.length
24 | }
25 | return unescape(document.cookie.substring(start, end))
26 | }
27 | }
28 | return ''
29 | }
30 |
31 | function _setCookie(name, value, expire) {
32 | let date = new Date()
33 | date.setDate(date.getDate() + expire)
34 | document.cookie = name + '=' + escape(value) + '; path=/' +
35 | (expire ? ';expires=' + date.toGMTString() : '')
36 | }
--------------------------------------------------------------------------------
/webpack/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "loader",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "loaders/ml-loader.js",
6 | "scripts": {
7 | "test": "jest",
8 | "start": "webpack --profile --config webpack.config.js --hide-modules "
9 | },
10 | "author": "",
11 | "license": "ISC",
12 | "devDependencies": {
13 | "autoprefixer": "9.4.2",
14 | "babel-core": "^6.26.3",
15 | "babel-jest": "^24.9.0",
16 | "babel-polyfill": "^6.26.0",
17 | "babel-preset-env": "^1.7.0",
18 | "css-loader": "^3.4.0",
19 | "extract-css-chunks-webpack-plugin": "3.2.1",
20 | "jest": "^24.9.0",
21 | "loader-utils": "^1.2.3",
22 | "memory-fs": "^0.5.0",
23 | "postcss": "7.0.6",
24 | "postcss-loader": "3.0.0",
25 | "postcss-pxtorem": "4.0.1",
26 | "progressbar.js": "^1.0.1",
27 | "regenerator-runtime": "^0.13.3",
28 | "schema-utils": "^2.6.1",
29 | "stylus": "0.54.5",
30 | "stylus-loader": "3.0.2",
31 | "vue-style-loader": "4.1.2",
32 | "webpack": "^4.41.5",
33 | "webpack-cli": "^3.3.10"
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/webpack4-ssr-config/client/views/test/data.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
Count is : {{count}}
7 |
count延迟了1秒赋值
8 |
ajax接口返回{{testResult}}
9 |
10 |
11 |
35 |
--------------------------------------------------------------------------------
/webpack4-ssr-config/client/views/test/ajax.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
proxy配置(项目目录constants.js文件中): { '/api': 'http://restapi.amap.com' }
4 |
接口URL: {{requestUrl}}
5 |
API接口测试
6 |
result:{{result}}
7 |
8 |
9 |
34 |
--------------------------------------------------------------------------------
/webpack4-ssr-config/client/config.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | // 引入http请求插件
3 | import http from './../config/http'
4 | // 引入log日志插件
5 | import { addRequestInterceptor, addResponseInterceptor } from './../config/http/http'
6 | import titleMixin from './utils/title'
7 | // 引入log日志插件
8 | import vueLogger from './../config/logger/vue-logger'
9 |
10 | // 注册插件
11 | Vue.use(http)
12 | Vue.use(vueLogger)
13 | Vue.mixin(titleMixin)
14 |
15 | // request前自动添加api配置
16 | addRequestInterceptor(
17 | (config) => {
18 | /*统一加/api前缀*/
19 | config.url = `/api${config.url}`
20 | return config
21 | },
22 | (error) => {
23 | return Promise.reject(error)
24 | }
25 | )
26 |
27 | // http 返回response前处理
28 | addResponseInterceptor(
29 | (response) => {
30 | /*todo 在这里统一前置处理请求响应 */
31 | return Promise.resolve(response.data)
32 | },
33 | (error) => {
34 | /*
35 | * todo 统一处理500、400等错误状态
36 | * 这里reject下,交给entry-server.js的处理
37 | */
38 | const { response, request } = error
39 | return Promise.reject({ code: response.status, data: response.data, method: request.method, path: request.path })
40 | }
41 | )
--------------------------------------------------------------------------------
/webpack3-basic-config/client/router.js:
--------------------------------------------------------------------------------
1 | /* loading */
2 | import VueRouter from 'vue-router'
3 | import routes from './routes'
4 | const ProgressBar = require('progressbar.js')
5 |
6 | const router = new VueRouter({
7 | mode: 'history',
8 | // base: '/book',
9 | routes
10 | })
11 |
12 | const doc = global.document
13 |
14 | // 响应式 SVG 进度条
15 | let line = null
16 |
17 | router.beforeEach((to, from, next) => {
18 | // 进度条开始
19 | if (line) line.destroy()
20 | line = new ProgressBar.Line('body', {
21 | color: '#009ce5',
22 | strokeWidth: 0.2,
23 | svgStyle: {
24 | position: 'fixed',
25 | zIndex: '10001',
26 | top: 0,
27 | left: 0,
28 | right: 0,
29 | maxHeight: '2px'
30 | }
31 | })
32 | line.animate(0.8, {
33 | duration: 500
34 | })
35 | next()
36 | })
37 |
38 | router.afterEach((route) => {
39 | // 设置标题
40 | doc.title = route.meta.title || '首页'
41 | // 进度条结束
42 | if (line) {
43 | line.animate(1, {
44 | duration: 1000
45 | }, () => {
46 | line.destroy()
47 | line = null
48 | })
49 | }
50 | })
51 |
52 | export default router
53 |
--------------------------------------------------------------------------------
/webpack4-ssr-config/client/assets/css/reset.css:
--------------------------------------------------------------------------------
1 | body, h1, h2, h3, h4, h5, h6, hr, p, blockquote, dl, dt, dd, ul, ol, li, pre, form, fieldset, legend, button, input, textarea, th, td {
2 | margin: 0;
3 | padding: 0;
4 | }
5 |
6 | body, button, input, select, textarea {
7 | font: 12PX/1.5 tahoma, arial, 'microsoft yahei', sans-serif
8 | }
9 |
10 | h1, h2, h3, h4, h5, h6 {
11 | font-size: 100%;
12 | }
13 |
14 | address, cite, dfn, em, var {
15 | font-style: normal;
16 | }
17 |
18 | code, kbd, pre, samp {
19 | font-family: couriernew, courier, monospace;
20 | }
21 |
22 | small {
23 | font-size: 12PX;
24 | }
25 |
26 | ul, ol {
27 | list-style: none;
28 | }
29 |
30 | a {
31 | text-decoration: none;
32 | }
33 |
34 | a:hover {
35 | text-decoration: underline;
36 | }
37 |
38 | sup {
39 | vertical-align: text-top;
40 | }
41 |
42 | sub {
43 | vertical-align: text-bottom;
44 | }
45 |
46 | legend {
47 | color: #000;
48 | }
49 |
50 | fieldset, img {
51 | border: 0;
52 | }
53 |
54 | button, input, select, textarea {
55 | font-size: 100%;
56 | }
57 |
58 | table {
59 | border-collapse: collapse;
60 | border-spacing: 0;
61 | }
--------------------------------------------------------------------------------
/webpack3-basic-config/client/assets/css/common.css:
--------------------------------------------------------------------------------
1 | body, h1, h2, h3, h4, h5, h6, hr, p, blockquote, dl, dt, dd, ul, ol, li, pre, form, fieldset, legend, button, input, textarea, th, td {
2 | margin: 0;
3 | padding: 0;
4 | }
5 |
6 | body, button, input, select, textarea {
7 | font: 12PX/1.5 tahoma, arial, 'microsoft yahei', sans-serif
8 | }
9 |
10 | h1, h2, h3, h4, h5, h6 {
11 | font-size: 100%;
12 | }
13 |
14 | address, cite, dfn, em, var {
15 | font-style: normal;
16 | }
17 |
18 | code, kbd, pre, samp {
19 | font-family: couriernew, courier, monospace;
20 | }
21 |
22 | small {
23 | font-size: 12PX;
24 | }
25 |
26 | ul, ol {
27 | list-style: none;
28 | }
29 |
30 | a {
31 | text-decoration: none;
32 | }
33 |
34 | a:hover {
35 | text-decoration: underline;
36 | }
37 |
38 | sup {
39 | vertical-align: text-top;
40 | }
41 |
42 | sub {
43 | vertical-align: text-bottom;
44 | }
45 |
46 | legend {
47 | color: #000;
48 | }
49 |
50 | fieldset, img {
51 | border: 0;
52 | }
53 |
54 | button, input, select, textarea {
55 | font-size: 100%;
56 | }
57 |
58 | table {
59 | border-collapse: collapse;
60 | border-spacing: 0;
61 | }
--------------------------------------------------------------------------------
/webpack3-basic-config/config/vue-loader.conf.js:
--------------------------------------------------------------------------------
1 | const postcss = require('./postcss.conf')()
2 | const ExtractTextPlugin = require('extract-text-webpack-plugin')
3 |
4 | /**
5 | * 组装vue-loader配置
6 | * @param {string} env 环境,可能的值prod|dev
7 | * @return {object} 配置
8 | **/
9 | module.exports = function (env) {
10 | const config = {
11 | loader: 'vue-loader',
12 | options: {
13 | // 去除模板中的空格
14 | preserveWhitespace: false,
15 | // postcss配置,把vue文件中的样式部分,做后续处理
16 | postcss,
17 | },
18 | }
19 | // webpack打包时,提取css
20 | if (env === 'prod') {
21 | // 生产环境
22 | config.options.loaders = {
23 | css: ExtractTextPlugin.extract({
24 | use: ['css-loader'],
25 | fallback: 'vue-style-loader',
26 | }),
27 | stylus: ExtractTextPlugin.extract({
28 | use: ['css-loader', 'stylus-loader'],
29 | fallback: 'vue-style-loader',
30 | }),
31 | }
32 | } else {
33 | // 开发环境
34 | config.options.loaders = {
35 | css: ['vue-style-loader', 'css-loader'],
36 | stylus: ['vue-style-loader', 'css-loader', 'stylus-loader',],
37 | }
38 | }
39 | return config
40 | }
41 |
--------------------------------------------------------------------------------
/react-base-webpack/config/webpack.config.dev.js:
--------------------------------------------------------------------------------
1 | /**
2 | * webpack dev配置
3 | * Created by zdliuccit on 2018/11/1.
4 | */
5 | const webpack = require('webpack')
6 | const merge = require('webpack-merge')
7 | const base = require('./webpack.config.base')()
8 | const appWebpack = require('./../app.config').webpack
9 |
10 | Object.keys(appWebpack.entry).forEach(function (name) {
11 | appWebpack.entry[name] = ['webpack-hot-middleware/client?path=/__webpack_hmr&timeout=2000&reload=true'].concat(appWebpack.entry[name])
12 | })
13 | const config = merge(base, {
14 | mode: 'development',
15 | devtool: '#cheap-module-source-map',
16 | module: {
17 | rules: [
18 | {
19 | test: /\.css$/,
20 | use: ['style-loader', 'css-loader', 'postcss-loader']
21 | },
22 | {
23 | test: /\.scss$/,
24 | use: ['style-loader', 'css-loader', 'postcss-loader', 'sass-loader']
25 | },
26 | ]
27 | },
28 | plugins: [
29 | new webpack.DefinePlugin({
30 | 'process.env': {
31 | NODE_ENV: '"development"',
32 | REACT_ENV: '"client"',
33 | },
34 | }),
35 | new webpack.HotModuleReplacementPlugin(),
36 | ]
37 | }, appWebpack)
38 |
39 | module.exports = config
40 |
--------------------------------------------------------------------------------
/webpack4-basic-config/src/config.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import VueRouter from 'vue-router'
3 | import http from '@config/utils/http'
4 | import vueLogger from '@config/utils/logger/vue-logger'
5 | import {addRequestInterceptor, addResponseInterceptor} from '@config/utils/http/http'
6 | import elementUI from 'element-ui'
7 | import 'element-ui/lib/theme-chalk/index.css'
8 |
9 | // 引入自定义业务组件
10 | import components from './components'
11 | // 注册插件
12 | Vue.use(http)
13 | Vue.use(vueLogger)
14 | Vue.use(VueRouter)
15 | Vue.use(elementUI)
16 |
17 | components.forEach(comp => {
18 | Vue.component(`ml-${comp.name}`, comp)
19 | })
20 |
21 | // request前自动添加api配置
22 | addRequestInterceptor(
23 | (config) => {
24 | config.url = `/api${config.url}`
25 | return config
26 | },
27 | (error) => {
28 | return Promise.reject(error)
29 | }
30 | )
31 |
32 | // 返回response前处理
33 | addResponseInterceptor(
34 | (response) => {
35 | // 在这里统一前置处理请求响应
36 | if (Number(response.status) !== 200) {
37 | // 全局notify有问题,还是自己处理吧
38 | return Promise.reject(response.data)
39 | }
40 | return Promise.resolve(response.data)
41 | },
42 | (error) => {
43 | return Promise.reject(error || '出错了')
44 | }
45 | )
46 |
--------------------------------------------------------------------------------
/koa-app/app/model/UserModel.js:
--------------------------------------------------------------------------------
1 | /**
2 | * User model
3 | */
4 |
5 | import mongoose, { Schema } from 'mongoose'
6 |
7 | const UserSchema = Schema({
8 | account: {
9 | type: String,
10 | required: true,
11 | trim: true
12 | },
13 | password: {
14 | type: String,
15 | required: true,
16 | trim: true
17 | },
18 | nickName: {
19 | type: String,
20 | required: true,
21 | trim: true
22 | },
23 | phone: {
24 | type: Number,
25 | min: 10,
26 | max: 20,
27 | required: true,
28 | },
29 | createTime: {
30 | type: Date,
31 | default: Date.now
32 | }
33 | });
34 |
35 | UserSchema.statics = {
36 | /**
37 | * 查找
38 | * @param data
39 | */
40 | async findUser(data = {}) {
41 | return await this.findOne(data);
42 | },
43 | /**
44 | * 创建用户
45 | * @param data
46 | */
47 | async register(data = {}) {
48 | const result = await this.create(data);
49 | return result
50 | },
51 | /**
52 | * 删除
53 | * @param data
54 | */
55 | async delete(data) {
56 | const result = await this.remove(data);
57 | return result
58 | },
59 | }
60 |
61 | const UserModel = mongoose.model('User', UserSchema);
62 |
63 | export default UserModel
64 |
--------------------------------------------------------------------------------
/webpack4-ssr-config/config/koa.server.js:
--------------------------------------------------------------------------------
1 | /**
2 | * koa2 server 入口
3 | * Created by zdliuccit on 2018/7/6.
4 | */
5 | const Koa = require('koa')
6 | const koaCompress = require('koa-compress')()
7 |
8 | const loggerMiddleware = require('koa-logger')()
9 | const staticMiddleWare = require('./middle/staticMiddleWare')
10 | const errorMiddleware = require('./middle/errorMiddleWare')
11 | const proxyMiddleWare = require('./middle/proxyMiddleWare')
12 | const vueKoaSSR = require('./vue.koa.ssr')
13 | const currentIP = require('ip').address()
14 |
15 | const appConfig = require('./../app.config')
16 | const uri = `http://${currentIP}:${appConfig.appPort}`
17 |
18 | // koa server
19 | const app = new Koa()
20 |
21 | // 中间件,
22 | const middleWares = [
23 | // 打印请求与响应 日志
24 | loggerMiddleware,
25 | // 压缩响应
26 | koaCompress,
27 | // 错误处理
28 | errorMiddleware,
29 | // 静态资源中间件
30 | staticMiddleWare(),
31 | ]
32 | middleWares.forEach((middleware) => {
33 | if (!middleware) {
34 | return
35 | }
36 | app.use(middleware)
37 | })
38 |
39 | // vue ssr处理
40 | vueKoaSSR(app, uri)
41 |
42 | // http代理中间件
43 | app.use(proxyMiddleWare())
44 |
45 | console.log(`\n> Starting server... ${uri} \n`)
46 |
47 | // 错误处理
48 | app.on('error', (err) => {
49 | // console.error('Server error: \n%s\n%s ', err.stack || '')
50 | })
51 |
52 | app.listen(appConfig.appPort)
53 |
--------------------------------------------------------------------------------
/webpack4-ssr-config/client/store/modules/test.js:
--------------------------------------------------------------------------------
1 | const state = {
2 | count: 0,
3 | testResult: null
4 | }
5 |
6 | const getters = {
7 | getCount: state => state.count,
8 | getTestResult: state => state.testResult
9 | }
10 |
11 | const mutations = {
12 | INCREMENT: (state) => {
13 | state.count++
14 | },
15 | DECREMENT: (state) => {
16 | state.count--
17 | },
18 | INITCOUNT: (state, COUNT) => {
19 | state.count = COUNT
20 | },
21 | TESTRESULT: (state, data) => {
22 | state.testResult = data
23 | }
24 | }
25 |
26 | const actions = {
27 | increment({ state, commit }) {
28 | commit('INCREMENT')
29 | },
30 | decrement({ state, commit }) {
31 | commit('DECREMENT')
32 | },
33 | loading({ commit, rootState: { $http } }) {
34 | // return new Promise(resolve => {
35 | // setTimeout(() => {
36 | // resolve()
37 | // }, 1000)
38 | // }).then(() => {
39 | // commit('INITCOUNT', 67)
40 | // commit('INITCOUNT', 67)
41 | // })
42 | return $http.get('/v3/assistant/coordinate/convert?key=ff0bcf778c5eeb93bd8b068b6e3f7781&locations=116.481499,39.990475|116.481499,39.990375')
43 | .then(res => {
44 | commit('INITCOUNT', 269)
45 | commit('TESTRESULT', res)
46 | })
47 | },
48 | resetCount({ commit }) {
49 | commit('INITCOUNT', 67)
50 | }
51 | }
52 |
53 | export default {
54 | state,
55 | getters,
56 | mutations,
57 | actions
58 | }
59 |
--------------------------------------------------------------------------------
/koa-app/app/plugins/http.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by zdliuccit on 2019/1/14.
3 | * @file axios封装
4 | * export default http 接口请求
5 | * export addRequestInterceptor 请求前拦截器
6 | * export addResponseInterceptor 请求后拦截器
7 | * export setCookies 同步cookie
8 | */
9 | import axios from 'axios'
10 |
11 | const currentIP = require('ip').address()
12 | const appConfig = require('./../../app.config')
13 |
14 | const defaultHeaders = {
15 | Accept: 'application/json, text/plain, */*; charset=utf-8',
16 | 'Content-Type': 'application/json; charset=utf-8',
17 | Pragma: 'no-cache',
18 | 'Cache-Control': 'no-cache',
19 | }
20 | Object.assign(axios.defaults.headers.common, defaultHeaders)
21 |
22 | if (!process.browser) {
23 | axios.defaults.baseURL = `http://${currentIP}:${appConfig.appPort}`
24 | }
25 | const methods = ['get', 'post', 'put', 'delete', 'patch', 'options', 'request', 'head']
26 |
27 | const $http = {}
28 | methods.forEach(method => {
29 | $http[method] = axios[method].bind(axios)
30 | })
31 |
32 | export const addRequestInterceptor = (resolve, reject) => {
33 | if (axios.interceptors.request.handlers.length === 0) axios.interceptors.request.use(resolve, reject)
34 | }
35 | export const addResponseInterceptor = (resolve, reject) => {
36 | if (axios.interceptors.response.handlers.length === 0) axios.interceptors.response.use(resolve, reject)
37 | }
38 | export const setCookies = Cookies => axios.defaults.headers.cookie = Cookies
39 |
40 | export default $http
41 |
--------------------------------------------------------------------------------
/webpack4-ssr-config/config/webpack.server.config.js:
--------------------------------------------------------------------------------
1 | /**
2 | * webpack server配置
3 | * Created by zdliuccit on 2018/7/6.
4 | */
5 | const webpack = require('webpack')
6 | const path = require('path')
7 | const merge = require('webpack-merge')
8 | const nodeExternals = require('webpack-node-externals')
9 | const baseConfig = require('./webpack.base.config')()
10 | const VueSSRServerPlugin = require('vue-server-renderer/server-plugin')
11 | const isProd = process.env.NODE_ENV === 'production'
12 |
13 | module.exports = merge(baseConfig, {
14 | // 指定生成后的运行环境在node
15 | target: 'node',
16 | mode: isProd ? 'production' : 'development',
17 | // 配置编译的入口文件
18 | entry: path.join(process.cwd(), 'client/entry-server.js'),
19 | // 设置输出文件名,并设置模块导出为commonjs2类型
20 | output: {
21 | filename: 'server-bundle.js',
22 | libraryTarget: 'commonjs2'
23 | },
24 | // 外置化应用程序依赖模块。可以使服务器构建速度更快,
25 | // 并生成较小的 bundle 文件。
26 | externals: nodeExternals({
27 | // 不要外置化 webpack 需要处理的依赖模块。
28 | // 你可以在这里添加更多的文件类型。例如,未处理 *.vue 原始文件,
29 | // 你还应该将修改 `global`(例如 polyfill)的依赖模块列入白名单
30 | whitelist: [/\.vue$/, /\.css$/]
31 | }),
32 | // 这是将服务器的整个输出
33 | // 构建为单个 JSON 文件的插件。
34 | // 默认文件名为 `vue-ssr-server-bundle.json`
35 | plugins: [
36 | new webpack.DefinePlugin({
37 | 'process.env.NODE_ENV': JSON.stringify(isProd ? 'production' : 'development'),
38 | 'process.env.VUE_ENV': '"server"'
39 | }),
40 | new VueSSRServerPlugin()
41 | ]
42 | })
43 |
--------------------------------------------------------------------------------
/webpack/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 | const ExtractCssChunks = require("extract-css-chunks-webpack-plugin")
3 |
4 | const mlPlugin = require('./loaders/ms-plugin');
5 |
6 | function resolve(dir) {
7 | return path.resolve(process.cwd(), dir)
8 | }
9 |
10 | module.exports = {
11 | mode: 'development',
12 | devtool: '#cheap-module-source-map',
13 | // 入口模块配置
14 | entry: resolve('src/index.js'),
15 | // 输出模块配置
16 | output: {
17 | // 输出到这个目录下
18 | path: resolve('dist'),
19 | // 生成的文件名, [name] 即为entry配置中的key
20 | filename: '[name].js',
21 | // 异步模块文件名
22 | chunkFilename: '[id].js',
23 | publicPath: '/'
24 | },
25 | // 寻找模块时的一些缺省设置
26 | resolveLoader: {
27 | modules: ['node_modules', resolve('loaders')],
28 | },
29 | resolve: {
30 | // 补充扩展名
31 | extensions: ['.js'],
32 | },
33 | module: {
34 | rules: [
35 | {
36 | test: /\.js$/,
37 | use: [{
38 | loader: 'ml-loader',
39 | options: {
40 | name: 'ml',
41 | test: '123213',
42 | }
43 | }],
44 | },
45 | {
46 | test: /\.css$/,
47 | use: [ExtractCssChunks.loader, 'css-loader'],
48 | },
49 | ]
50 | },
51 | plugins: [
52 | new ExtractCssChunks({
53 | filename: 'assets/css/[name].[chunkhash:8].css',
54 | chunkFilename: 'assets/css/[id].[chunkhash:8].css',
55 | }),
56 | new mlPlugin({ tip: '参数' })
57 | ]
58 | }
59 |
--------------------------------------------------------------------------------
/webpack4-ssr-config/config/http/http.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by zdliuccit on 2019/1/14.
3 | * @file axios封装
4 | * export default http 接口请求
5 | * export addRequestInterceptor 请求前拦截器
6 | * export addResponseInterceptor 请求后拦截器
7 | * export setCookies 同步cookie
8 | */
9 | import axios from 'axios'
10 |
11 | const currentIP = require('ip').address()
12 | const appConfig = require('./../../app.config')
13 |
14 | const defaultHeaders = {
15 | Accept: 'application/json, text/plain, */*; charset=utf-8',
16 | 'Content-Type': 'application/json; charset=utf-8',
17 | Pragma: 'no-cache',
18 | 'Cache-Control': 'no-cache',
19 | }
20 | Object.assign(axios.defaults.headers.common, defaultHeaders)
21 |
22 | if (!process.browser) {
23 | axios.defaults.baseURL = `http://${currentIP}:${appConfig.appPort}`
24 | }
25 | const methods = ['get', 'post', 'put', 'delete', 'patch', 'options', 'request', 'head']
26 |
27 | const http = {}
28 | methods.forEach(method => {
29 | http[method] = axios[method].bind(axios)
30 | })
31 |
32 | export const addRequestInterceptor = (resolve, reject) => {
33 | if (axios.interceptors.request.handlers.length === 0) axios.interceptors.request.use(resolve, reject)
34 | }
35 | export const addResponseInterceptor = (resolve, reject) => {
36 | if (axios.interceptors.response.handlers.length === 0) axios.interceptors.response.use(resolve, reject)
37 | }
38 | export const setCookies = Cookies => axios.defaults.headers.cookie = Cookies
39 |
40 | export default http
41 |
--------------------------------------------------------------------------------
/react-base-webpack/config/middle/proxyToken.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by zdliuccit on 2018/11/1.
3 | * proxyMiddleWare中间件token处理
4 | * @type {string}
5 | */
6 | const logger = require('../logger/koa-logger')('proxyToken')
7 | // 带token http头
8 | const accessTokenHeaderName = 'x-access-token'
9 | // 请求来源 http头
10 | const accessOriginHeaderName = 'x-access-origin'
11 |
12 | // 默认cookie配置
13 | const defaultCookieConfig = {
14 | name: '_atk',
15 | httpOnly: true,
16 | overwrite: true,
17 | // 长期有效(20年)
18 | maxAge: 1000 * 60 * 60 * 24 * 365 * 20,
19 | }
20 |
21 | module.exports = function createRedis() {
22 | const cookieConfig = Object.assign({}, defaultCookieConfig)
23 | return {
24 | // 处理请求时的token操作
25 | async handleRequest(ctx) {
26 | return {
27 | [accessOriginHeaderName]: ctx.query.accessOrigin || 'WAP',
28 | }
29 | },
30 |
31 | // 处理响应时的token操作
32 | async handleResponse(ctx) {
33 | logger.info('HandleResponse headers:', ctx.response.headers)
34 | const responseToken = ctx.response.headers[accessTokenHeaderName]
35 |
36 | // 如果后端响应头里没有token,则不设置cookie
37 | if (!responseToken) return
38 | logger.info(`Token found: ${responseToken}', it will be set to cookie.`)
39 |
40 | // 这里koa-better-http-proxy已经把代理响应头复制到原始响应头了
41 | ctx.cookies.set(cookieConfig.name, responseToken, cookieConfig)
42 |
43 | // 删除代理响应的"X-Access-Token"http头
44 | delete ctx.response.headers[accessTokenHeaderName]
45 | delete ctx.response.headers[accessOriginHeaderName]
46 | },
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/webpack3-basic-config/config/utils/token.js:
--------------------------------------------------------------------------------
1 | /**
2 | * token处理
3 | * @type {string}
4 | */
5 | const logger = require('./logger/koa-logger')('proxyMiddleWare')
6 | // 带token http头
7 | const accessTokenHeaderName = 'x-access-token'
8 | // 请求来源 http头
9 | const accessOriginHeaderName = 'x-access-origin'
10 |
11 | // 默认cookie配置
12 | const defaultCookieConfig = {
13 | name: '_atk',
14 | httpOnly: true,
15 | overwrite: true,
16 | // 长期有效(20年)
17 | maxAge: 1000 * 60 * 60 * 24 * 365 * 20,
18 | }
19 |
20 | module.exports = function createRedis () {
21 | const cookieConfig = Object.assign({}, defaultCookieConfig)
22 |
23 | return {
24 | /**
25 | * 处理请求时的token操作
26 | * @param {ctx} ctx - koa ctx
27 | * @return {Object} - 需要添加的header头
28 | */
29 | async handleRequest(ctx) {
30 | return {
31 | [accessOriginHeaderName]: ctx.query.accessOrigin || 'WAP',
32 | }
33 | },
34 | /**
35 | * 处理响应时的token操作
36 | * @param {ctx} ctx - koa ctx
37 | */
38 | async handleResponse(ctx) {
39 | logger.info('HandleResponse headers:', ctx.response.headers)
40 | const responseToken = ctx.response.headers[accessTokenHeaderName]
41 | // 如果后端响应头里没有token,则不设置cookie
42 | if (!responseToken) {
43 | return
44 | }
45 | logger.info(`Token found: ${responseToken}', it will be set to cookie.`)
46 | // 这里koa-better-http-proxy已经把代理响应头复制到原始响应头了
47 | ctx.cookies.set(cookieConfig.name, responseToken, cookieConfig)
48 |
49 | // 删除代理响应的"X-Access-Token"http头
50 | delete ctx.response.headers[accessTokenHeaderName]
51 | delete ctx.response.headers[accessOriginHeaderName]
52 | },
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/webpack4-basic-config/config/utils/token.js:
--------------------------------------------------------------------------------
1 | /**
2 | * token处理
3 | * @type {string}
4 | */
5 | const logger = require('./logger/koa-logger')('proxyMiddleWare')
6 | // 带token http头
7 | const accessTokenHeaderName = 'x-access-token'
8 | // 请求来源 http头
9 | const accessOriginHeaderName = 'x-access-origin'
10 |
11 | // 默认cookie配置
12 | const defaultCookieConfig = {
13 | name: '_atk',
14 | httpOnly: true,
15 | overwrite: true,
16 | // 长期有效(20年)
17 | maxAge: 1000 * 60 * 60 * 24 * 365 * 20,
18 | }
19 |
20 | module.exports = function createRedis () {
21 | const cookieConfig = Object.assign({}, defaultCookieConfig)
22 |
23 | return {
24 | /**
25 | * 处理请求时的token操作
26 | * @param {ctx} ctx - koa ctx
27 | * @return {Object} - 需要添加的header头
28 | */
29 | async handleRequest(ctx) {
30 | return {
31 | [accessOriginHeaderName]: ctx.query.accessOrigin || 'WAP',
32 | }
33 | },
34 | /**
35 | * 处理响应时的token操作
36 | * @param {ctx} ctx - koa ctx
37 | */
38 | async handleResponse(ctx) {
39 | logger.info('HandleResponse headers:', ctx.response.headers)
40 | const responseToken = ctx.response.headers[accessTokenHeaderName]
41 | // 如果后端响应头里没有token,则不设置cookie
42 | if (!responseToken) {
43 | return
44 | }
45 | logger.info(`Token found: ${responseToken}', it will be set to cookie.`)
46 | // 这里koa-better-http-proxy已经把代理响应头复制到原始响应头了
47 | ctx.cookies.set(cookieConfig.name, responseToken, cookieConfig)
48 |
49 | // 删除代理响应的"X-Access-Token"http头
50 | delete ctx.response.headers[accessTokenHeaderName]
51 | delete ctx.response.headers[accessOriginHeaderName]
52 | },
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/webpack3-basic-config/config/webpack.config.dev.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by liuzhengdong on 2017/7/6.
3 | */
4 | const webpack = require('webpack')
5 | const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
6 |
7 | const config = require('./webpack.config.base')('dev')
8 | const postcss = require('./postcss.conf')()
9 |
10 | // cheap-module-eval-source-map is faster for development
11 | config.devtool = '#cheap-module-source-map'
12 |
13 | // add hot-reload related code to entry chunks
14 | Object.keys(config.entry).forEach(function (name) {
15 | config.entry[name] = ['webpack-hot-middleware/client?path=/__webpack_hmr&timeout=2000&reload=true'].concat(config.entry[name])
16 | })
17 |
18 | config.module.rules.push(
19 | {
20 | test: /\.css$/,
21 | use: ['style-loader', 'css-loader', {
22 | loader: 'postcss-loader',
23 | options: { plugins: postcss, sourceMap: 'inline' }
24 | }],
25 | },
26 | {
27 | test: /\.(styl|stylus)$/,
28 | use: ['style-loader', 'css-loader', {
29 | loader: 'postcss-loader',
30 | options: { plugins: postcss, sourceMap: 'inline' }
31 | },
32 | 'stylus-loader'
33 | ],
34 | }
35 | )
36 | config.plugins = (config.plugins || []).concat([
37 | //你可以理解为,通过配置了DefinePlugin,那么这里面的标识就相当于全局变量,你的业务代码可以直接使用配置的标识。
38 | new webpack.DefinePlugin({
39 | 'process.env': {
40 | NODE_ENV: '"development"',
41 | VUE_ENV: '"client"',
42 | },
43 | }),
44 | // new webpack.optimize.MinChunkSizePlugin({
45 | // minChunkSize: 100000 // Minimum number of characters
46 | // }),
47 | // 全局开启代码热替换
48 | new webpack.HotModuleReplacementPlugin(),
49 | new webpack.NoEmitOnErrorsPlugin(),
50 | new FriendlyErrorsPlugin(),
51 | ])
52 |
53 | module.exports = config
54 |
--------------------------------------------------------------------------------
/webpack4-basic-config/config/webpack.config.prod.js:
--------------------------------------------------------------------------------
1 | /**
2 | * webpack server配置
3 | * Created by zdliuccit on 2018/7/6.
4 | */
5 | const webpack = require('webpack')
6 | const merge = require('webpack-merge')
7 | const config = require('./webpack.config.base')()
8 | const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin')
9 | const ExtractCssChunks = require("extract-css-chunks-webpack-plugin")
10 |
11 | module.exports = merge(config, {
12 | // 设置代码调试map
13 | devtool: false,
14 | mode: 'production',
15 | optimization: {
16 | runtimeChunk: {
17 | name: 'ml-node'
18 | },
19 | splitChunks: {
20 | cacheGroups: {
21 | commons: {
22 | chunks: 'initial',
23 | minChunks: 5,
24 | },
25 | vendor: {
26 | chunks: 'all',
27 | name: 'vendor',
28 | test: /node_modules/,
29 | priority: -10,
30 | reuseExistingChunk: false,
31 | },
32 | },
33 | },
34 | },
35 | plugins: [
36 | new webpack.DefinePlugin({
37 | 'process.env': {
38 | NODE_ENV: JSON.stringify("production"),
39 | },
40 | }),
41 | new ExtractCssChunks({
42 | filename: 'assets/css/[name].[chunkhash:8].css',
43 | chunkFilename: 'assets/css/[id].[chunkhash:8].css',
44 | }),
45 | // 限制文件最小KB
46 | new webpack.optimize.MinChunkSizePlugin({
47 | minChunkSize: 20000
48 | }),
49 | new OptimizeCssAssetsPlugin(
50 | {
51 | cssProcessor: require('cssnano'),
52 | cssProcessorOptions: {
53 | // postcss那边已经处理过autoprefixer了,这里把它关掉,否则会导致浏览器前缀兼容范围问题
54 | autoprefixer: false,
55 | discardComments: {removeAll: true}
56 | },
57 | }
58 | ),]
59 | })
60 |
--------------------------------------------------------------------------------
/webpack3-basic-config/config/utils/httpMiddleWare.js:
--------------------------------------------------------------------------------
1 | /**
2 | * http中间件
3 | * 为ctx添加http方法, 然后在后续的路由中, ctx.http.get(url: '/url') 即可
4 | */
5 | const axios = require('axios')
6 |
7 | const methods = ['get', 'post', 'put', 'delete']
8 |
9 | /**
10 | * 默认请求头
11 | */
12 | const defaultHeaders = {
13 | Accept: 'application/json, text/plain, */*; charset=utf-8',
14 | 'Content-Type': 'application/json; charset=utf-8',
15 | Pragma: 'no-cache',
16 | 'Cache-Control': 'no-cache',
17 | }
18 |
19 | const axiosInstance = axios.create({
20 | timeout: 20 * 1000,
21 | headers: defaultHeaders,
22 | })
23 |
24 | // http request 拦截器
25 | axiosInstance.interceptors.request.use(
26 | (config) => {
27 | config._reqeustStartTimestamp = Date.now()
28 | return config
29 | },
30 | (error) => {
31 | return Promise.reject(error)
32 | }
33 | )
34 |
35 | // http response 拦截器
36 | axiosInstance.interceptors.response.use(
37 | (response) => {
38 | return response
39 | },
40 | (error) => {
41 | return Promise.reject(error)
42 | }
43 | )
44 |
45 | /**
46 | * @returns {Function} ctx function
47 | */
48 | module.exports = function () {
49 | return function httpMiddleware (ctx, next) {
50 | const http = {}
51 | methods.forEach(method => {
52 | http[method] = (...args) => {
53 | let config
54 | const emptyConfig = { headers: {} }
55 | // axios的get和delete方法木有body,只能接受两个参数
56 | if (method === 'get' || method === 'delete') {
57 | config = args[1] = args[1] || emptyConfig
58 | } else {
59 | config = args[2] = args[2] || emptyConfig
60 | }
61 | // 把浏览器的cookie的带上
62 | config.headers.cookie = ctx.req.headers.cookie || ''
63 | return axiosInstance[method](...args)
64 | }
65 | })
66 | ctx.http = http
67 | return next()
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/webpack3-basic-config/config/koa-prod-server.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by liuzhengdong on 2017/7/13.
3 | */
4 | const Koa = require('koa')
5 | const KoaRouter = require('koa-router')()
6 | const currentIP = require('ip').address()
7 |
8 | const appConfig = require('./../app.config')
9 |
10 | const loggerMiddleware = require('koa-logger')()
11 | const errorMiddleware = require('./utils/errorMiddleWare')
12 | const staticMiddleWare = require('./utils/staticMiddleWare')
13 | const setCookieMiddleware = require('./utils/setCookieMiddleWare')
14 | const httpMiddleware = require('./utils/httpMiddleWare')
15 | const spaMiddleWare = require('./utils/spaMiddleWare')
16 | const proxyMiddleware = require('./utils/proxyMiddleWare')
17 |
18 | const app = new Koa()
19 | const uri = 'http://' + currentIP + ':' + appConfig.appPort
20 |
21 | // 中间件,一组async函数,generator函数需要convert转换
22 | const middleWares = [
23 | // 打印请求与响应 日志
24 | loggerMiddleware,
25 | // 静态资源中间件
26 | staticMiddleWare(),
27 | // 压缩响应
28 | require('koa-compress')(),
29 | // 错误处理
30 | errorMiddleware,
31 | // 手动设置cookie方法
32 | setCookieMiddleware,
33 | // http中间件
34 | httpMiddleware(),
35 | // spa单页应用处理,非api后段请求返回index.html
36 | spaMiddleWare(),
37 | // 插入自定义中间件
38 | ...appConfig.middleWares,
39 | // 路由
40 | KoaRouter.middleware(),
41 | // 代理中间件
42 | proxyMiddleware(),
43 | ]
44 |
45 | middleWares.forEach((middleware) => {
46 | if (!middleware) {
47 | return
48 | }
49 | app.use(middleware)
50 | })
51 |
52 | console.log('> Starting production server address >>> ' + uri)
53 | // 错误处理
54 | app.on('error', (err) => {
55 | console.error('Server error: \n%s\n%s ', err.stack || '')
56 | })
57 |
58 | const server = app.listen(appConfig.appPort)
59 |
60 | process.on('SIGTERM', () => {
61 | console.log('Stopping dev server')
62 | devMiddleware.close()
63 | server.close(() => {
64 | process.exit(0)
65 | })
66 | })
--------------------------------------------------------------------------------
/webpack4-ssr-config/client/entry-client.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @file 运行于浏览器
3 | * Created by zdliuccit on 2018/7/6.
4 | * */
5 | import Vue from 'vue'
6 |
7 | import { createApp } from './index'
8 | import ProgressBar from './components/ProgressBar.vue'
9 | // 引入http请求
10 | import http from './../config/http/http'
11 | // global progress bar
12 | const bar = Vue.prototype.$bar = new Vue(ProgressBar).$mount()
13 | document.body.appendChild(bar.$el)
14 |
15 | // a global mixin that calls `asyncData` when a route component's params change
16 | Vue.mixin({
17 | beforeRouteUpdate(to, from, next) {
18 | const { asyncData } = this.$options
19 | if (asyncData) {
20 | asyncData({ store: this.$store, route: to })
21 | .then(next)
22 | .catch(next)
23 | } else {
24 | next()
25 | }
26 | }
27 | })
28 |
29 | const { app, router, store } = createApp()
30 |
31 | // prime the store with server-initialized state.
32 | // the state is determined during SSR and inlined in the page markup.
33 | if (window.__INITIAL_STATE__) {
34 | store.replaceState(window.__INITIAL_STATE__)
35 | // 客户端和服务端保持一致
36 | store.state.$http = http
37 | }
38 |
39 | router.onReady(() => {
40 | router.beforeResolve((to, from, next) => {
41 | const matched = router.getMatchedComponents(to)
42 | const prevMatched = router.getMatchedComponents(from)
43 | let diffed = false
44 | const activated = matched.filter((c, i) => {
45 | return diffed || (diffed = (prevMatched[i] !== c))
46 | })
47 | const asyncDataHooks = activated.map(c => c.asyncData).filter(_ => _)
48 | if (!asyncDataHooks.length) {
49 | return next()
50 | }
51 | bar.start()
52 | Promise.all(asyncDataHooks.map(hook => hook({ store, router, route: to })))
53 | .then(() => {
54 | bar.finish()
55 | next()
56 | })
57 | .catch(next)
58 | })
59 |
60 | app.$mount('#app')
61 | })
--------------------------------------------------------------------------------
/webpack4-ssr-config/client/entry-server.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 运行于服务器
3 | * Created by zdliuccit on 2018/7/6.
4 | * */
5 |
6 | import { createApp } from './index'
7 |
8 | // 引入http请求
9 | import http from './../config/http/http'
10 | // 处理ssr期间cookies穿透
11 | import { setCookies } from './../config/http/http'
12 |
13 | const { app } = createApp()
14 |
15 | // 这里假定 App.vue 模板中根元素具有 `id="app"`
16 | app.$mount('#app')
17 |
18 | export default context => {
19 | // 因为有可能会是异步路由钩子函数或组件,所以我们将返回一个 Promise,
20 | // 以便服务器能够等待所有的内容在渲染前,
21 | // 就已经准备就绪。
22 | return new Promise((resolve, reject) => {
23 | const { app, router, store } = createApp()
24 |
25 | const { url } = context
26 | const { fullPath } = router.resolve(url).route
27 |
28 | if (fullPath !== url) {
29 | return reject({ url: fullPath })
30 | }
31 |
32 | // 设置服务器端 router 的位置,路由配置里如果设置过base,url需要把url.replace(base,'')掉,不然会404
33 | router.push(url)
34 |
35 | // 等到 router 将可能的异步组件和钩子函数解析完
36 | router.onReady(() => {
37 | // 获取该url路由下的所有Component,这些组件定义在Vue Router中。
38 | const matchedComponents = router.getMatchedComponents()
39 | // 匹配不到的路由,执行 reject 函数,并返回 404
40 | if (!matchedComponents.length) {
41 | return reject({ code: 404 })
42 | }
43 | // SSR期间同步cookies
44 | setCookies(context.cookies || {})
45 | // http注入到rootState上,方便store里调用
46 | store.state.$http = http
47 | // 使用Promise.all执行匹配到的Component的asyncData方法,即预取数据
48 | Promise.all(matchedComponents.map(({ asyncData }) => asyncData && asyncData({
49 | store,
50 | router,
51 | route: router.currentRoute,
52 | }))).then(() => {
53 | // 在所有预取钩子(preFetch hook) resolve 后,
54 | // 我们的 store 现在已经填充入渲染应用程序所需的状态。
55 | // 当我们将状态附加到上下文,
56 | // 并且 `template` 选项用于 renderer 时,
57 | // 状态将自动序列化为 `window.__INITIAL_STATE__`,并注入 HTML。
58 | context.state = store.state
59 | resolve(app)
60 | }).catch(reject)
61 | }, reject)
62 | })
63 | }
--------------------------------------------------------------------------------
/webpack4-ssr-config/client/views/home.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Webpack4 + Vue2 + Koa2 构建SSR应用脚手架
4 |
16 |
17 |
18 |
23 |
--------------------------------------------------------------------------------
/webpack3-basic-config/client/view/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
{{msg}}
5 |
6 |
代理配置: http://restapi.amap.com/v3/
7 |
测试接口: {{testUrl}}
8 |
9 |
10 |
11 |
12 |
返回结果: {{result}}
13 |
14 |
15 |
16 |
47 |
71 |
78 |
--------------------------------------------------------------------------------
/webpack3-basic-config/config/webpack.config.prod.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by liuzhengdong on 2017/7/6.
3 | */
4 | const path = require('path')
5 | const webpack = require('webpack')
6 | const ExtractTextPlugin = require('extract-text-webpack-plugin')
7 | const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
8 | const config = require('./webpack.config.base')('prod')
9 | const postcss = require('./postcss.conf')()
10 |
11 | config.output.filename = '[name].[chunkhash:7].js'
12 | config.output.chunkFilename = '[id].[chunkhash:7].js'
13 |
14 | config.devtool = false
15 |
16 | config.module.rules.push(
17 | {
18 | test: /\.css$/,
19 | use: ExtractTextPlugin.extract({
20 | use: ['css-loader', { loader: 'postcss-loader', options: { plugins: postcss } }],
21 | fallback: 'style-loader',
22 | }),
23 | },
24 | {
25 | test: /\.styl$/,
26 | use: ExtractTextPlugin.extract({
27 | use: ['css-loader', { loader: 'postcss-loader', options: { plugins: postcss } }, 'stylus-loader'],
28 | fallback: 'style-loader',
29 | }),
30 | }
31 | )
32 |
33 | config.plugins = (config.plugins || []).concat([
34 | new webpack.LoaderOptionsPlugin({
35 | // webpack 2.0之后,这边不配置px转rem不会成功!!!蛋疼
36 | options: {
37 | postcss: postcss
38 | },
39 | }),
40 | // 定义全局常量
41 | new webpack.DefinePlugin({
42 | 'process.env': {
43 | //注意一个单引号一个双引号…… 这里是要将 "production" 替换到文件里面
44 | NODE_ENV: JSON.stringify("production"),
45 | VUE_ENV: JSON.stringify("client"),
46 | },
47 | }),
48 | // 合并公共模块为单独文件
49 | new webpack.optimize.CommonsChunkPlugin({
50 | name: 'vendor',
51 | filename: 'vendor-[hash].min.js',
52 | }),
53 | // js压缩
54 | new webpack.optimize.UglifyJsPlugin({
55 | comments: false, // 去掉注释
56 | compress: {
57 | warnings: false, // 不显示警告
58 | drop_console: false,
59 | },
60 | }),
61 | // 分离css文件
62 | new ExtractTextPlugin('[name].[contenthash:8].css'),
63 |
64 | // optimize \ minimize CSS assets
65 | new OptimizeCSSPlugin({
66 | cssProcessorOptions: {
67 | safe: true,
68 | // postcss那边已经处理过autoprefixer了,这里把它关掉,否则会导致浏览器前缀兼容范围问题
69 | autoprefixer: false,
70 | },
71 | }),
72 | ])
73 |
74 | module.exports = config
75 |
--------------------------------------------------------------------------------
/react-base-webpack/config/koa.server.js:
--------------------------------------------------------------------------------
1 | /**
2 | * koa2 server 入口
3 | * Created by zdliuccit on 2018/11/1.
4 | */
5 | const Koa = require('koa')
6 | const convert = require('koa-convert')
7 | const webpack = require('webpack')
8 | const merge = require('webpack-merge')
9 |
10 | const KoaRouter = require('koa-router')()
11 | const koaCompress = require('koa-compress')()
12 | const loggerMiddleware = require('koa-logger')()
13 | const errorMiddleware = require('./middle/errorMiddleWare')
14 | const proxyMiddleware = require('./middle/proxyMiddleWare')
15 | const spaMiddleWare = require('./middle/spaMiddleWare')
16 | const webpackDevMiddleware = require('koa-webpack-dev-middleware')
17 | const webpackHotMiddleware = require('koa-webpack-hot-middleware')
18 |
19 | const opn = require('opn')
20 | const config = merge(require('./webpack.config.dev'))
21 | const appConfig = require('./../app.config')
22 | const currentIP = require('ip').address()
23 | const uri = `http://${currentIP}:${appConfig.appPort}`
24 | const clientCompiler = webpack(config)
25 | const devMiddleware = webpackDevMiddleware(clientCompiler, {
26 | publicPath: config.output.publicPath,
27 | headers: {'Access-Control-Allow-Origin': '*'},
28 | stats: {
29 | colors: true,
30 | modules: false,
31 | },
32 | noInfo: false,
33 | })
34 | // koa server
35 | const app = new Koa()
36 |
37 | // 中间件,一组async函数,generator函数需要convert转换
38 | const middleWares = [
39 | // 打印请求与响应 日志
40 | loggerMiddleware,
41 | // 压缩响应
42 | koaCompress,
43 | // 错误处理
44 | errorMiddleware,
45 | // webpack开发中间件
46 | convert(devMiddleware),
47 | // webpack热替换中间件
48 | convert(webpackHotMiddleware(clientCompiler)),
49 | // spa单页应用处理,非api后段请求返回index.html
50 | spaMiddleWare(),
51 | // 路由
52 | KoaRouter.middleware(),
53 | // 代理中间件
54 | proxyMiddleware(),
55 | ]
56 |
57 | middleWares.forEach((middleware) => {
58 | if (!middleware) return
59 | app.use(middleware)
60 | })
61 |
62 | console.log('> Starting dev server...')
63 |
64 | devMiddleware.waitUntilValid(() => {
65 | console.log('> Listening at ' + uri + '\n')
66 | // opn(uri)
67 | })
68 |
69 | // 错误处理
70 | app.on('error', (err) => {
71 | console.error('Server error: \n%s\n%s ', err.stack || '')
72 | })
73 |
74 | app.listen(appConfig.appPort)
75 |
76 |
--------------------------------------------------------------------------------
/react-base-webpack/config/middle/spaMiddleWare.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by zdliuccit on 2018/11/1.
3 | * 基于 https://github.com/bripkens/connect-history-api-fallback 改造
4 | */
5 | const path = require('path')
6 | const fs = require('fs')
7 | const logger = require('./../logger/koa-logger')('spaMiddleWare')
8 | const currentIP = require('ip').address()
9 |
10 | const IS_DEBUG = true
11 | const appConfig = require('./../../app.config')
12 |
13 | const defaultOptions = { include: /^\/(api|static|public|v3)/ }
14 |
15 | /**
16 | * 读取构建过的文件,public目录下
17 | * @param {String} filename 文件名
18 | * @return {String} 文件内容
19 | */
20 | function readBuiltFile(filename) {
21 | return fs.readFileSync(path.join(process.cwd(), 'dist', filename), 'utf-8')
22 | }
23 |
24 | let indexHTML
25 |
26 | // 生产模式
27 | if (!IS_DEBUG) {
28 | indexHTML = readBuiltFile('index.html')
29 | }
30 |
31 | /**
32 | * 单页应用中间件
33 | * @param {Object} options 配置项
34 | * @return {function} 中间件
35 | */
36 | module.exports = function (options) {
37 | options = Object.assign({}, defaultOptions, options)
38 | return async function spa(ctx, next) {
39 | if (!options.include.test(ctx.url)) {
40 | /**
41 | * 开发模式从koa2服务中获取index
42 | */
43 | await new Promise((resolve) => {
44 | if (indexHTML && !IS_DEBUG) {
45 | resolve()
46 | } else {
47 | require('http').get('http://' + currentIP + ':' + appConfig.appPort, (res) => {
48 | res.on('data', (chunk) => {
49 | logger.info('Fetching index.html succeed.')
50 | indexHTML = chunk.toString('utf-8')
51 | resolve()
52 | })
53 | }).on('error', (e) => {
54 | logger.error(`Fetching index.html error: ${e.message}`)
55 | process.exit(1)
56 | })
57 | }
58 | }).then(doRender)
59 |
60 | /**
61 | * 返回HTML
62 | */
63 | function doRender() {
64 | const res = ctx.res
65 | res.statusCode = 200
66 | // 这句很重要,否则会影响到weinre调试
67 | res.setHeader('Content-Type', 'text/html; charset=utf-8')
68 | res.end(`${indexHTML}`)
69 | logger.info('Page routing request')
70 | }
71 | } else {
72 | return next()
73 | }
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/webpack3-basic-config/config/utils/spaMiddleWare.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 基于 https://github.com/bripkens/connect-history-api-fallback 改造
3 | */
4 | const path = require('path')
5 | const fs = require('fs')
6 | const logger = require('./logger/koa-logger')('spaMiddleWare')
7 | const currentIP = require('ip').address()
8 |
9 | const {IS_DEBUG} = require('../utils/env')
10 | const appConfig = require('./../../app.config')
11 |
12 | const defaultOptions = {include: /^\/(api|static|public|v3)/}
13 |
14 | /**
15 | * 读取构建过的文件,public目录下
16 | * @param {String} filename 文件名
17 | * @return {String} 文件内容
18 | */
19 | function readBuiltFile(filename) {
20 | return fs.readFileSync(path.join(process.cwd(), 'public', filename), 'utf-8')
21 | }
22 |
23 | let indexHTML
24 |
25 | // 生产模式
26 | if (!IS_DEBUG) {
27 | indexHTML = readBuiltFile('index.html')
28 | }
29 |
30 | /**
31 | * 单页应用中间件
32 | * @param {Object} options 配置项
33 | * @return {function} 中间件
34 | */
35 | module.exports = function (options) {
36 | options = Object.assign({}, defaultOptions, options)
37 | return async function spa(ctx, next) {
38 | if (!options.include.test(ctx.url)) {
39 | /**
40 | * 开发模式从koa2服务中获取index
41 | */
42 | await new Promise((resolve) => {
43 | if (indexHTML && !IS_DEBUG) {
44 | resolve()
45 | } else {
46 | require('http').get('http://' + currentIP + ':' + appConfig.appPort, (res) => {
47 | res.on('data', (chunk) => {
48 | logger.info('Fetching index.html succeed.')
49 | indexHTML = chunk.toString('utf-8')
50 | resolve()
51 | })
52 | }).on('error', (e) => {
53 | logger.error(`Fetching index.html error: ${e.message}`)
54 | process.exit(1)
55 | })
56 | }
57 | }).then(doRender)
58 |
59 | /**
60 | * 返回HTML
61 | */
62 | function doRender() {
63 | const res = ctx.res
64 | res.statusCode = 200
65 | // 这句很重要,否则会影响到weinre调试
66 | res.setHeader('Content-Type', 'text/html; charset=utf-8')
67 | res.end(`${indexHTML}`)
68 | logger.info('Page routing request')
69 | return
70 | }
71 | } else {
72 | return next()
73 | }
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/webpack4-basic-config/config/utils/spaMiddleWare.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 基于 https://github.com/bripkens/connect-history-api-fallback 改造
3 | */
4 | const path = require('path')
5 | const fs = require('fs')
6 | const logger = require('./logger/koa-logger')('spaMiddleWare')
7 | const currentIP = require('ip').address()
8 |
9 | const {IS_DEBUG} = require('../utils/env')
10 | const appConfig = require('./../../app.config')
11 |
12 | const defaultOptions = {include: /^\/(api|static|public|v3)/}
13 |
14 | /**
15 | * 读取构建过的文件,public目录下
16 | * @param {String} filename 文件名
17 | * @return {String} 文件内容
18 | */
19 | function readBuiltFile(filename) {
20 | return fs.readFileSync(path.join(process.cwd(), 'public', filename), 'utf-8')
21 | }
22 |
23 | let indexHTML
24 |
25 | // 生产模式
26 | if (!IS_DEBUG) {
27 | indexHTML = readBuiltFile('index.html')
28 | }
29 |
30 | /**
31 | * 单页应用中间件
32 | * @param {Object} options 配置项
33 | * @return {function} 中间件
34 | */
35 | module.exports = function (options) {
36 | options = Object.assign({}, defaultOptions, options)
37 | return async function spa(ctx, next) {
38 | if (!options.include.test(ctx.url)) {
39 | /**
40 | * 开发模式从koa2服务中获取index
41 | */
42 | await new Promise((resolve) => {
43 | if (indexHTML && !IS_DEBUG) {
44 | resolve()
45 | } else {
46 | require('http').get('http://' + currentIP + ':' + appConfig.appPort, (res) => {
47 | res.on('data', (chunk) => {
48 | logger.info('Fetching index.html succeed.')
49 | indexHTML = chunk.toString('utf-8')
50 | resolve()
51 | })
52 | }).on('error', (e) => {
53 | logger.error(`Fetching index.html error: ${e.message}`)
54 | process.exit(1)
55 | })
56 | }
57 | }).then(doRender)
58 |
59 | /**
60 | * 返回HTML
61 | */
62 | function doRender() {
63 | const res = ctx.res
64 | res.statusCode = 200
65 | // 这句很重要,否则会影响到weinre调试
66 | res.setHeader('Content-Type', 'text/html; charset=utf-8')
67 | res.end(`${indexHTML}`)
68 | logger.info('Page routing request')
69 | return
70 | }
71 | } else {
72 | return next()
73 | }
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/webpack3-basic-config/config/utils/logger/vue-logger.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by liuzhengdong on 2017/9/21.
3 | * 日志打印器 class
4 | */
5 | import { IS_DEBUG } from './../env'
6 |
7 | class Logger {
8 | /**
9 | * 构造函数
10 | * @param filename 调用的文件名
11 | */
12 | constructor (filename) {
13 | this.filename = filename
14 | }
15 | }
16 |
17 | /**
18 | * 定义方法
19 | * @type {{info: string, log: string, warn: string, error: string}}
20 | */
21 | const methods = {
22 | log: 'color: green',
23 | info: 'color:#6495ED',
24 | warn: 'color: #cc33cc',
25 | error: 'color: red',
26 | }
27 | /**
28 | * 将方法绑定到原型上
29 | */
30 | Object.entries(methods).forEach(([method, color]) => {
31 | Logger.prototype[method] = function (...args) {
32 | // 非生产环境
33 | if (!IS_DEBUG) {
34 | return
35 | }
36 | args.unshift(`%c[${this.filename}]:`, color)
37 | console[method](...args)
38 | }
39 | })
40 |
41 | /**
42 | * 定义 VueLogger class
43 | */
44 | class VueLogger {
45 | constructor (filename) {
46 | const logger = new Logger(filename)
47 | Object.keys(methods).forEach(method => {
48 | this[method] = (vm, ...args) => {
49 | // 不存在vue实例时,简单打印
50 | if (!vm) {
51 | return
52 | }
53 | if (vm._isVue !== true) {
54 | logger[method].call(logger, vm, ...args)
55 | return
56 | }
57 | // 组件当前__file
58 | const filePath = vm.$options._parentVnode.componentOptions.Ctor.options.__file
59 | // 截取组件名称
60 | const componentName = filePath.slice(filePath.lastIndexOf('/') + 1) || '(unkonwn component name)'
61 | // 当前路由路径
62 | const fullPath = vm.$route.fullPath || '(unkonwn route fullPath)'
63 | logger[method].call(logger, ...args, `@${componentName}`, `#${fullPath}`)
64 | }
65 | })
66 | }
67 | }
68 |
69 | const vueLogger = new VueLogger('component')
70 | const componentLogger = {}
71 | /**
72 | * 暴露install钩子,供vue注册
73 | * @param {Vue} Vue - Vue构造器类
74 | */
75 | componentLogger.install = function (Vue) { // 基础打印器
76 | Object.keys(methods).forEach((method) => {
77 | Vue.prototype[method] = function (...args) {
78 | vueLogger[method].call({}, this, ...args)
79 | }
80 | })
81 | }
82 |
83 | export default componentLogger
--------------------------------------------------------------------------------
/webpack4-basic-config/config/utils/logger/vue-logger.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by liuzhengdong on 2017/9/21.
3 | * 日志打印器 class
4 | */
5 | import { IS_DEBUG } from './../env'
6 |
7 | class Logger {
8 | /**
9 | * 构造函数
10 | * @param filename 调用的文件名
11 | */
12 | constructor (filename) {
13 | this.filename = filename
14 | }
15 | }
16 |
17 | /**
18 | * 定义方法
19 | * @type {{info: string, log: string, warn: string, error: string}}
20 | */
21 | const methods = {
22 | log: 'color: green',
23 | info: 'color:#6495ED',
24 | warn: 'color: #cc33cc',
25 | error: 'color: red',
26 | }
27 | /**
28 | * 将方法绑定到原型上
29 | */
30 | Object.entries(methods).forEach(([method, color]) => {
31 | Logger.prototype[method] = function (...args) {
32 | // 非生产环境
33 | if (!IS_DEBUG) {
34 | return
35 | }
36 | args.unshift(`%c[${this.filename}]:`, color)
37 | console[method](...args)
38 | }
39 | })
40 |
41 | /**
42 | * 定义 VueLogger class
43 | */
44 | class VueLogger {
45 | constructor (filename) {
46 | const logger = new Logger(filename)
47 | Object.keys(methods).forEach(method => {
48 | this[method] = (vm, ...args) => {
49 | // 不存在vue实例时,简单打印
50 | if (!vm) {
51 | return
52 | }
53 | if (vm._isVue !== true) {
54 | logger[method].call(logger, vm, ...args)
55 | return
56 | }
57 | // 组件当前__file
58 | const filePath = vm.$options._parentVnode.componentOptions.Ctor.options.__file
59 | // 截取组件名称
60 | const componentName = filePath.slice(filePath.lastIndexOf('/') + 1) || '(unkonwn component name)'
61 | // 当前路由路径
62 | const fullPath = vm.$route.fullPath || '(unkonwn route fullPath)'
63 | logger[method].call(logger, ...args, `@${componentName}`, `#${fullPath}`)
64 | }
65 | })
66 | }
67 | }
68 |
69 | const vueLogger = new VueLogger('component')
70 | const componentLogger = {}
71 | /**
72 | * 暴露install钩子,供vue注册
73 | * @param {Vue} Vue - Vue构造器类
74 | */
75 | componentLogger.install = function (Vue) { // 基础打印器
76 | Object.keys(methods).forEach((method) => {
77 | Vue.prototype[method] = function (...args) {
78 | vueLogger[method].call({}, this, ...args)
79 | }
80 | })
81 | }
82 |
83 | export default componentLogger
--------------------------------------------------------------------------------
/webpack4-ssr-config/config/logger/vue-logger.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by zdliuccit on 2017/9/21.
3 | * 日志打印器 class
4 | */
5 | const IS_DEBUG = process.env.NODE_ENV !== 'production'
6 |
7 | class Logger {
8 | /**
9 | * 构造函数
10 | * @param filename 调用的文件名
11 | */
12 | constructor(filename) {
13 | this.filename = filename
14 | }
15 | }
16 |
17 | /**
18 | * 定义方法
19 | * @type {{info: string, log: string, warn: string, error: string}}
20 | */
21 | const methods = {
22 | log: 'color: green',
23 | info: 'color:#6495ED',
24 | warn: 'color: #cc33cc',
25 | error: 'color: red',
26 | }
27 | /**
28 | * 将方法绑定到原型上
29 | */
30 | Object.entries(methods).forEach(([method, color]) => {
31 | Logger.prototype[method] = function (...args) {
32 | // 非生产环境
33 | if (!IS_DEBUG) {
34 | return
35 | }
36 | args.unshift(`%c[${this.filename}]:`, color)
37 | console[method](...args)
38 | }
39 | })
40 |
41 | /**
42 | * 定义 VueLogger class
43 | */
44 | class VueLogger {
45 | constructor(filename) {
46 | const logger = new Logger(filename)
47 | Object.keys(methods).forEach(method => {
48 | this[method] = (vm, ...args) => {
49 | // 不存在vue实例时,简单打印
50 | if (!vm) {
51 | return
52 | }
53 | if (vm._isVue !== true) {
54 | logger[method].call(logger, vm, ...args)
55 | return
56 | }
57 | // 组件当前__file
58 | const filePath = vm.$options._parentVnode.componentOptions.Ctor.options.__file
59 | // 截取组件名称
60 | const componentName = filePath.slice(filePath.lastIndexOf('/') + 1) || '(unkonwn component name)'
61 | // 当前路由路径
62 | const fullPath = vm.$route.fullPath || '(unkonwn route fullPath)'
63 | logger[method].call(logger, ...args, `@${componentName}`, `#${fullPath}`)
64 | }
65 | })
66 | }
67 | }
68 |
69 | const vueLogger = new VueLogger('component')
70 | const componentLogger = {}
71 | /**
72 | * 暴露install钩子,供vue注册
73 | * @param {Vue} Vue - Vue构造器类
74 | */
75 | componentLogger.install = function (Vue) { // 基础打印器
76 | Object.keys(methods).forEach((method) => {
77 | Vue.prototype[method] = function (...args) {
78 | vueLogger[method].call({}, this, ...args)
79 | }
80 | })
81 | }
82 |
83 | export default componentLogger
--------------------------------------------------------------------------------
/webpack4-basic-config/config/koa-dev-server.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by liuzhengdong on 2017/7/13.
3 | */
4 | const Koa = require('koa')
5 | const KoaRouter = require('koa-router')()
6 | const webpack = require('webpack')
7 | const currentIP = require('ip').address()
8 |
9 | const opn = require('opn')
10 | const loggerMiddleware = require('koa-logger')()
11 | const convert = require('koa-convert')
12 | const webpackDevMiddleware = require('koa-webpack-dev-middleware')
13 | const webpackHotMiddleware = require('koa-webpack-hot-middleware')
14 |
15 | const appConfig = require('./../app.config')
16 | const config = require('./webpack.config.dev')
17 | const clientCompiler = webpack(config)
18 |
19 | const proxyMiddleware = require('./utils/proxyMiddleWare')
20 | const errorMiddleware = require('./utils/errorMiddleWare')
21 | const spaMiddleWare = require('./utils/spaMiddleWare')
22 | const staticMiddleWare = require('./utils/staticMiddleWare')
23 |
24 | const app = new Koa()
25 | const uri = 'http://' + currentIP + ':' + appConfig.appPort
26 |
27 | const devMiddleware = webpackDevMiddleware(clientCompiler, {
28 | publicPath: config.output.publicPath,
29 | headers: {'Access-Control-Allow-Origin': '*'},
30 | stats: {
31 | colors: true,
32 | modules: false,
33 | },
34 | noInfo: false,
35 | })
36 |
37 | // 中间件,一组async函数,generator函数需要convert转换
38 | const middleWares = [
39 | // 打印请求与响应 日志
40 | loggerMiddleware,
41 | // 压缩响应
42 | require('koa-compress')(),
43 | // 错误处理
44 | errorMiddleware,
45 | // 资源中间件
46 | staticMiddleWare(),
47 | // webpack开发中间件
48 | convert(devMiddleware),
49 | // webpack热替换中间件
50 | convert(webpackHotMiddleware(clientCompiler)),
51 | // spa单页应用处理,非api后段请求返回index.html
52 | spaMiddleWare(),
53 | // 路由
54 | KoaRouter.middleware(),
55 | // 代理中间件
56 | proxyMiddleware(),
57 | ]
58 |
59 | middleWares.forEach((middleware) => {
60 | if (!middleware) {
61 | return
62 | }
63 | app.use(middleware)
64 | })
65 |
66 | console.log('> Starting dev server...')
67 |
68 | devMiddleware.waitUntilValid(() => {
69 | console.log('> Listening at ' + uri + '\n')
70 | opn(uri)
71 | })
72 |
73 | // 错误处理
74 | app.on('error', (err) => {
75 | console.error('Server error: \n%s\n%s ', err.stack || '')
76 | })
77 |
78 | app.listen(appConfig.appPort)
79 |
--------------------------------------------------------------------------------
/react-base-webpack/config/webpack.config.base.js:
--------------------------------------------------------------------------------
1 | /**
2 | * webpack base配置
3 | * Created by zdliuccit on 2018/11/1.
4 | */
5 | const path = require('path')
6 | const webpack = require('webpack')
7 | const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin')
8 | const HtmlWebpackPlugin = require('html-webpack-plugin')
9 | const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
10 |
11 | const isProd = process.env.NODE_ENV === 'production'
12 | const appConfig = require('./../app.config')
13 | const appVersion = new Date().getTime()
14 |
15 | function resolve(dir) {
16 | return path.resolve(process.cwd(), dir)
17 | }
18 |
19 | const favicon = path.join(process.cwd(), 'favicon.ico')
20 |
21 | module.exports = function () {
22 | const config = {
23 | output: {
24 | path: resolve('dist'),
25 | filename: `[name].[${isProd ? 'chunkhash' : 'hash'}:8].js`,
26 | chunkFilename: '[id].js',
27 | publicPath: '/'
28 | },
29 | resolve: {
30 | extensions: ['.js', '.jsx', '.json', '.scss'],
31 | alias: {
32 | '@': resolve('client'),
33 | }
34 | },
35 | module: {
36 | rules: [
37 | // js,jsx 转译
38 | {
39 | test: /\.(js|jsx)$/,
40 | use: ['babel-loader'],
41 | exclude: /(node_modules|bower_components)/,
42 | },
43 | {
44 | test: /\.json$/,
45 | use: 'json-loader',
46 | },
47 | {
48 | test: /\.(gif|jpg|jpeg|png|bmp|svg|ico)(\?.*)?$/,
49 | use: [{
50 | loader: 'url-loader',
51 | options: {
52 | limit: 1,
53 | name: 'assets/images/[name].[hash:8].[ext]',
54 | },
55 | }],
56 | },
57 | {
58 | test: /\.(woff|woff2|eot|ttf)(\?.*)?$/,
59 | use: [{
60 | loader: 'url-loader',
61 | options: {
62 | limit: 8912,
63 | name: 'assets/font/[name].[hash:8].[ext]',
64 | },
65 | }],
66 | },
67 | ],
68 | },
69 | plugins: [
70 | new CaseSensitivePathsPlugin(),
71 | new HtmlWebpackPlugin({
72 | appVersion,
73 | favicon,
74 | filename: 'index.html',
75 | template: path.join(process.cwd(), 'index.template.ejs'),
76 | }),
77 | new FriendlyErrorsPlugin(),
78 | new webpack.optimize.LimitChunkCountPlugin({
79 | maxChunks: 1
80 | })
81 | ],
82 | }
83 | return config
84 | }
--------------------------------------------------------------------------------
/webpack3-basic-config/config/koa-dev-server.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by liuzhengdong on 2017/7/13.
3 | */
4 | const Koa = require('koa')
5 | const KoaRouter = require('koa-router')()
6 | const webpack = require('webpack')
7 | const currentIP = require('ip').address()
8 |
9 | const opn = require('opn')
10 | const loggerMiddleware = require('koa-logger')()
11 | const convert = require('koa-convert')
12 | const webpackDevMiddleware = require('koa-webpack-dev-middleware')
13 | const webpackHotMiddleware = require('koa-webpack-hot-middleware')
14 |
15 | const appConfig = require('./../app.config')
16 | const config = require('./webpack.config.dev')
17 | const clientCompiler = webpack(config)
18 |
19 | const setCookieMiddleware = require('./utils/setCookieMiddleWare')
20 | const httpMiddleware = require('./utils/httpMiddleWare')
21 | const proxyMiddleware = require('./utils/proxyMiddleWare')
22 | const errorMiddleware = require('./utils/errorMiddleWare')
23 | const spaMiddleWare = require('./utils/spaMiddleWare')
24 |
25 | const app = new Koa()
26 | const uri = 'http://' + currentIP + ':' + appConfig.appPort
27 |
28 | const devMiddleware = webpackDevMiddleware(clientCompiler, {
29 | publicPath: config.output.publicPath,
30 | headers: { 'Access-Control-Allow-Origin': '*' },
31 | stats: {
32 | colors: true,
33 | modules: false,
34 | },
35 | noInfo: false,
36 | })
37 |
38 | // 中间件,一组async函数,generator函数需要convert转换
39 | const middleWares = [
40 | // 打印请求与响应 日志
41 | loggerMiddleware,
42 | // 压缩响应
43 | require('koa-compress')(),
44 | // 错误处理
45 | errorMiddleware,
46 | // webpack开发中间件
47 | convert(devMiddleware),
48 | // webpack热替换中间件
49 | convert(webpackHotMiddleware(clientCompiler)),
50 | // 手动设置cookie方法
51 | setCookieMiddleware,
52 | // http中间件
53 | httpMiddleware(),
54 | // spa单页应用处理,非api后段请求返回index.html
55 | spaMiddleWare(),
56 | // 插入自定义中间件
57 | ...appConfig.middleWares,
58 | // 路由
59 | KoaRouter.middleware(),
60 | // 代理中间件
61 | proxyMiddleware(),
62 | ]
63 |
64 | middleWares.forEach((middleware) => {
65 | if (!middleware) {
66 | return
67 | }
68 | app.use(middleware)
69 | })
70 |
71 | console.log('> Starting dev server...')
72 |
73 | devMiddleware.waitUntilValid(() => {
74 | console.log('> Listening at ' + uri + '\n')
75 | opn(uri)
76 | })
77 |
78 | // 错误处理
79 | app.on('error', (err) => {
80 | console.error('Server error: \n%s\n%s ', err.stack || '')
81 | })
82 |
83 | const server = app.listen(appConfig.appPort)
84 |
85 | process.on('SIGTERM', () => {
86 | console.log('Stopping dev server')
87 | devMiddleware.close()
88 | server.close(() => {
89 | process.exit(0)
90 | })
91 | })
--------------------------------------------------------------------------------
/webpack4-ssr-config/client/components/ProgressBar.vue:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
86 |
87 |
100 |
--------------------------------------------------------------------------------
/webpack4-ssr-config/config/vue.koa.ssr.js:
--------------------------------------------------------------------------------
1 | /**
2 | * vue koa2 ssr中间件
3 | * Created by zdliuccit on 2018/7/6.
4 | */
5 | const fs = require('fs')
6 | const path = require('path')
7 | const LRU = require('lru-cache')
8 | const { createBundleRenderer } = require('vue-server-renderer')
9 | const isProd = process.env.NODE_ENV === 'production'
10 | const proxyConfig = require('./../app.config').proxy
11 | const setUpDevServer = require('./setup.dev.server')
12 |
13 | module.exports = function (app, uri) {
14 |
15 | const renderData = (ctx, renderer) => {
16 | const context = {
17 | url: ctx.url,
18 | title: 'Vue Koa2 SSR',
19 | cookies: ctx.request.headers.cookie
20 | }
21 | return new Promise((resolve, reject) => {
22 | renderer.renderToString(context, (err, html) => {
23 | if (err) {
24 | return reject(err)
25 | }
26 | resolve(html)
27 | })
28 | })
29 | }
30 |
31 | function createRenderer(bundle, options) {
32 | return createBundleRenderer(bundle, Object.assign(options, {
33 | cache: LRU({
34 | max: 1000,
35 | maxAge: 1000 * 60 * 15
36 | }),
37 | runInNewContext: false
38 | }))
39 | }
40 |
41 | function resolve(dir) {
42 | return path.resolve(process.cwd(), dir)
43 | }
44 |
45 | let renderer
46 | if (isProd) {
47 | // prod mode
48 | const template = fs.readFileSync(resolve('dist/index.html'), 'utf-8')
49 | const bundle = require(resolve('dist/vue-ssr-server-bundle.json'))
50 | const clientManifest = require(resolve('dist/vue-ssr-client-manifest.json'))
51 | renderer = createRenderer(bundle, {
52 | template,
53 | clientManifest
54 | })
55 | } else {
56 | // dev mode
57 | setUpDevServer(app, uri, (bundle, options) => {
58 | try {
59 | renderer = createRenderer(bundle, options)
60 | } catch (e) {
61 | console.log('\nbundle error', e)
62 | }
63 | }
64 | )
65 | }
66 | app.use(async (ctx, next) => {
67 | if (!renderer) {
68 | ctx.type = 'html'
69 | return ctx.body = 'waiting for compilation... refresh in a moment.';
70 | }
71 | if (Object.keys(proxyConfig).findIndex(vl => ctx.url.startsWith(vl)) > -1) {
72 | return next()
73 | }
74 | let html, status
75 | try {
76 | status = 200
77 | html = await renderData(ctx, renderer)
78 | } catch (e) {
79 | console.log('\ne', e)
80 | if (e.code === 404) {
81 | status = 404
82 | html = '404 | Not Found'
83 | } else {
84 | status = 500
85 | html = '500 | Internal Server Error'
86 | }
87 | }
88 | ctx.type = 'html'
89 | ctx.status = status ? status : ctx.status
90 | ctx.body = html
91 | })
92 | }
--------------------------------------------------------------------------------
/react-base-webpack/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-ssr-webpack",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "start": "cross-env NODE_ENV=development node config/index.js",
8 | "build": "rimraf dist && cross-env NODE_ENV=production webpack --config config/webpack.config.prod.js --progress --hide-modules",
9 | "test": "echo \"Error: no test specified\" && exit 1"
10 | },
11 | "author": "zdliuccit",
12 | "license": "ISC",
13 | "keywords": [
14 | "react",
15 | "vue-ssr",
16 | "ssr",
17 | "koa",
18 | "koa2",
19 | "webpack4"
20 | ],
21 | "dependencies": {
22 | "antd": "^3.10.4",
23 | "react": "^16.6.0",
24 | "react-dom": "^16.6.0",
25 | "react-router-dom": "^4.3.1",
26 | "redux": "^4.0.1"
27 | },
28 | "devDependencies": {
29 | "@babel/core": "7.1.2",
30 | "@babel/plugin-proposal-class-properties": "^7.1.0",
31 | "@babel/polyfill": "7.0.0",
32 | "@babel/preset-env": "7.1.0",
33 | "@babel/preset-react": "^7.0.0",
34 | "autoprefixer": "9.1.5",
35 | "axios": "0.18.0",
36 | "babel-eslint": "10.0.1",
37 | "babel-loader": "8.0.4",
38 | "babel-plugin-import": "^1.11.0",
39 | "case-sensitive-paths-webpack-plugin": "2.1.2",
40 | "cross-env": "5.2.0",
41 | "css-loader": "^1.0.0",
42 | "cssnano": "4.1.4",
43 | "eslint": "5.6.1",
44 | "eslint-config-standard": "12.0.0",
45 | "eslint-friendly-formatter": "4.0.1",
46 | "eslint-loader": "2.1.1",
47 | "eslint-plugin-html": "4.0.6",
48 | "eslint-plugin-import": "2.14.0",
49 | "eslint-plugin-node": "7.0.1",
50 | "eslint-plugin-promise": "4.0.1",
51 | "eslint-plugin-standard": "4.0.0",
52 | "extract-css-chunks-webpack-plugin": "3.1.1",
53 | "file-loader": "2.0.0",
54 | "friendly-errors-webpack-plugin": "1.7.0",
55 | "html-webpack-plugin": "3.2.0",
56 | "ip": "1.1.5",
57 | "json-loader": "0.5.7",
58 | "koa": "2.5.3",
59 | "koa-better-http-proxy": "0.2.4",
60 | "koa-compress": "2.0.0",
61 | "koa-convert": "1.2.0",
62 | "koa-logger": "3.2.0",
63 | "koa-router": "7.4.0",
64 | "koa-static": "5.0.0",
65 | "koa-webpack-dev-middleware": "2.0.2",
66 | "koa-webpack-hot-middleware": "1.0.3",
67 | "lru-cache": "4.1.3",
68 | "memory-fs": "0.4.1",
69 | "node-sass": "^4.9.4",
70 | "opn": "5.4.0",
71 | "optimize-css-assets-webpack-plugin": "5.0.1",
72 | "postcss": "7.0.4",
73 | "postcss-loader": "3.0.0",
74 | "postcss-pxtorem": "4.0.1",
75 | "sass-loader": "^7.1.0",
76 | "style-loader": "^0.23.1",
77 | "url-loader": "1.1.1",
78 | "webpack": "4.24.0",
79 | "webpack-cli": "3.1.2",
80 | "webpack-dev-middleware": "3.4.0",
81 | "webpack-hot-middleware": "2.24.2",
82 | "webpack-merge": "4.1.4"
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/react-base-webpack/config/webpack.config.prod.js:
--------------------------------------------------------------------------------
1 | /**
2 | * webpack prod配置
3 | * Created by zdliuccit on 2018/11/1.
4 | */
5 | const webpack = require('webpack')
6 | const merge = require('webpack-merge')
7 | const base = require('./webpack.config.base')()
8 | const appWebpack = require('./../app.config').webpack
9 | const ExtractCssChunks = require("extract-css-chunks-webpack-plugin")
10 | const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin')
11 |
12 | const config = merge(base, {
13 | mode: 'production',
14 | module: {
15 | rules: [
16 | {
17 | test: /\.css$/,
18 | use: [ExtractCssChunks.loader, 'css-loader', 'postcss-loader'],
19 | },
20 | {
21 | test: /\.scss$/,
22 | use: [ExtractCssChunks.loader, 'css-loader', 'postcss-loader', 'sass-loader'],
23 | },
24 | ]
25 | },
26 | plugins: [
27 | // 分离css文件
28 | new ExtractCssChunks({
29 | filename: 'css/[name].[chunkhash:8].css',
30 | chunkFilename: 'css/[id].[chunkhash:8].css',
31 | }),
32 | // 限制文件最小KB
33 | new webpack.optimize.MinChunkSizePlugin({
34 | minChunkSize: 20000
35 | }),
36 | new OptimizeCssAssetsPlugin(
37 | {
38 | cssProcessor: require('cssnano'),
39 | cssProcessorOptions: {
40 | // postcss那边已经处理过autoprefixer了,这里把它关掉,否则会导致浏览器前缀兼容范围问题
41 | autoprefixer: false,
42 | discardComments: { removeAll: true }
43 | },
44 | }
45 | ),
46 | ],
47 | // production模式下,将侧重于模块体积优化和线上部署,包含如下内容:
48 | // 开启所有的优化代码
49 | // 更小的bundle大小
50 | // 去除掉只在开发阶段运行的代码
51 | // Scope hoisting和Tree-shaking
52 | // 自动启用uglifyjs对代码进行压缩
53 | optimization: {
54 | minimize: true, //取代 new UglifyJsPlugin(/* ... */)
55 | providedExports: true,
56 | usedExports: true,
57 | //识别package.json中的sideEffects以剔除无用的模块,用来做tree-shake
58 | //依赖于optimization.providedExports和optimization.usedExports
59 | sideEffects: true,
60 | //取代 new webpack.optimize.ModuleConcatenationPlugin()
61 | concatenateModules: true,
62 | //取代 new webpack.NoEmitOnErrorsPlugin(),编译错误时不打印输出资源。
63 | noEmitOnErrors: true
64 | },
65 | optimization: {
66 | minimize: env === 'production' ? true : false, //是否进行代码压缩
67 | splitChunks: {
68 | chunks: "async",
69 | minSize: 30000, //模块大于30k会被抽离到公共模块
70 | minChunks: 1, //模块出现1次就会被抽离到公共模块
71 | maxAsyncRequests: 5, //异步模块,一次最多只能被加载5个
72 | maxInitialRequests: 3, //入口模块最多只能加载3个
73 | name: true,
74 | cacheGroups: {
75 | default: {
76 | minChunks: 2,
77 | priority: -20
78 | reuseExistingChunk: true,
79 | },
80 | vendors: {
81 | test: /[\\/]node_modules[\\/]/,
82 | priority: -10
83 | }
84 | }
85 | },
86 | runtimeChunk: {
87 | name: 'runtime'
88 | }
89 | }
90 | }, appWebpack)
91 |
92 | module.exports = config
93 |
--------------------------------------------------------------------------------
/webpack4-ssr-config/config/setup.dev.server.js:
--------------------------------------------------------------------------------
1 | /**
2 | * koa2 webpack4 开发服务
3 | * Created by zdliuccit on 2018/7/6.
4 | */
5 | const path = require('path')
6 | const MFS = require('memory-fs')
7 | const webpack = require('webpack')
8 | const clientConfig = require('./webpack.client.config')
9 | const serverConfig = require('./webpack.server.config')
10 | const webpackDevMiddleware = require('koa-webpack-dev-middleware')
11 | const webpackHotMiddleware = require('koa-webpack-hot-middleware')
12 | const convert = require('koa-convert')
13 |
14 | const opn = require('opn')
15 | const readFile = (fs, file) => fs.readFileSync(path.join(clientConfig.output.path, file), 'utf-8')
16 |
17 | module.exports = function setupDevServer(app, uri, cb) {
18 | let bundle
19 | let template
20 |
21 | const update = () => {
22 | if (bundle && template) {
23 | cb(bundle, {
24 | template,
25 | })
26 | }
27 | }
28 |
29 | // client
30 | clientConfig.entry.app = ['webpack-hot-middleware/client?path=/__webpack_hmr&timeout=2000&reload=true', clientConfig.entry.app]
31 | clientConfig.output.filename = '[name].js'
32 | clientConfig.plugins.push(
33 | new webpack.HotModuleReplacementPlugin(),
34 | new webpack.NoEmitOnErrorsPlugin()
35 | )
36 |
37 | // webpack config
38 | const clientCompiler = webpack(clientConfig)
39 |
40 | // dev middleware
41 | const devMiddleware = webpackDevMiddleware(clientCompiler, {
42 | publicPath: clientConfig.output.publicPath,
43 | noInfo: true,
44 | headers: { 'Access-Control-Allow-Origin': '*' },
45 | stats: {
46 | colors: true,
47 | modules: false,
48 | },
49 | })
50 |
51 | app.use(convert(devMiddleware))
52 |
53 | // hot update
54 | clientCompiler.plugin('done', stats => {
55 | const fs = devMiddleware.fileSystem
56 | stats = stats.toJson()
57 | stats.errors.forEach(err => console.error(err))
58 | stats.warnings.forEach(err => console.warn(err))
59 | if (stats.errors.length) return
60 |
61 | console.log('\nclient-dev...\n')
62 |
63 | let filePath = path.join(clientConfig.output.path, 'index.html')
64 | if (fs.existsSync(filePath)) {
65 | // 读取内存模板
66 | template = readFile(fs, 'index.html')
67 | }
68 | update()
69 | })
70 |
71 | // hot middleware
72 | app.use(convert(webpackHotMiddleware(clientCompiler)))
73 |
74 | // server
75 | const serverCompiler = webpack(serverConfig)
76 | const mfs = new MFS()
77 | serverCompiler.outputFileSystem = mfs
78 | serverCompiler.watch({}, (err, stats) => {
79 | if (err) throw err
80 | stats = stats.toJson()
81 | if (stats.errors.length) return
82 |
83 | console.log('server-dev...')
84 | bundle = JSON.parse(readFile(mfs, 'vue-ssr-server-bundle.json'))
85 | update()
86 | })
87 |
88 | devMiddleware.waitUntilValid(() => {
89 | console.log('\n> Listening at ' + uri + '\n')
90 | opn(uri)
91 | })
92 | }
93 |
--------------------------------------------------------------------------------
/webpack3-basic-config/config/eslintrc.conf.js:
--------------------------------------------------------------------------------
1 | /**
2 | * eslint规则配置,用于被业务工程引用
3 | */
4 | module.exports = {
5 | root: true,
6 | env: {
7 | // 环境定义了预定义的全局变量。
8 | browser: true,
9 | node: true,
10 | es6: true,
11 | mocha: true
12 | },
13 | parser: 'babel-eslint', //使用babel-eslint来作为eslint的解析器
14 | parserOptions: {
15 | // ECMAScript 版本
16 | ecmaVersion: 6,
17 | sourceType: 'module',
18 | // // 想使用的额外的语言特性:
19 | ecmaFeatures: {
20 | experimentalObjectRestSpread: true,
21 | }
22 | },
23 | extends: 'standard',
24 | plugins: [
25 | 'html',
26 | 'import',
27 | 'promise',
28 | ],
29 | // add your custom rules here
30 | rules: {
31 | // 禁止条件表达式中出现赋值操作符
32 | 'no-cond-assign': 2,
33 | // 允许console语句
34 | 'no-console': 1,
35 | // 允许 debugger
36 | 'no-debugger': 0,
37 | // 禁止 function 定义中出现重名参数
38 | 'no-dupe-args': 2,
39 | // var声明
40 | 'no-var': 1,
41 | // 分号;
42 | 'semi': [
43 | 0,
44 | 'always'
45 | ],
46 | // 使用 === 替代 == allow-null允许null和undefined==
47 | 'eqeqeq': [
48 | 2,
49 | 'allow-null'
50 | ],
51 | // 禁用 alert、confirm 和 prompt
52 | 'no-alert': 2,
53 | // 禁用 eval()
54 | 'no-eval': 2,
55 | // 禁用 with 语句
56 | 'no-with': 2,
57 | // 要求或禁止使用严格模式指令
58 | 'strict': 2,
59 | //////////////
60 | // 要求或禁止 var 声明中的初始化(初值)
61 | 'init-declarations': 2,
62 | // 不允许 catch 子句的参数与外层作用域中的变量同名
63 | 'no-catch-shadow': 0,
64 | // 禁止删除变量
65 | 'no-delete-var': 2,
66 | // 不允许标签与变量同名
67 | 'no-label-var': 2,
68 | // 禁用特定的全局变量
69 | 'no-restricted-globals': 0,
70 | // 禁止 var 声明 与外层作用域的变量同名
71 | 'no-shadow': 0,
72 | // 禁止覆盖受限制的标识符
73 | 'no-shadow-restricted-names': 2,
74 | // 禁用未声明的变量,除非它们在 /*global */ 注释中被提到
75 | 'no-undef': 2,
76 | // 禁止将变量初始化为 undefined
77 | 'no-undef-init': 2,
78 | // 禁止将 undefined 作为标识符
79 | 'no-undefined': 0,
80 | // 禁止出现未使用过的变量
81 | 'no-unused-vars': [
82 | 0,
83 | {
84 | 'vars': 'all',
85 | 'args': 'none'
86 | }
87 | ],
88 | // 不允许在变量定义之前使用它们
89 | 'no-use-before-define': 0,
90 | // 强制一行的最大长度
91 | 'max-len': [
92 | 1,
93 | 200
94 | ],
95 | // 文件末尾强制换行
96 | 'eol-last': 0,
97 | // 强制使用一致的反勾号、双引号或单引号
98 | 'quotes': [
99 | 2,
100 | 'single'
101 | ],
102 | // 禁止修改 const 声明的变量
103 | 'no-const-assign': 2,
104 | // 禁止标识符中有悬空下划线_bar
105 | 'no-underscore-dangle': 0,
106 | // 禁用行尾空格
107 | 'no-trailing-spaces': 2,
108 | // 禁用不必要的嵌套块
109 | 'no-lone-blocks': 2,
110 | // 强制在 JSX 属性中一致地使用双引号或单引号
111 | 'jsx-quotes': 0,
112 | // 函数定义时括号前面要不要有空格 这里忽略
113 | 'space-before-function-paren': [0, `always`],
114 | //对象字面量项尾不能有逗号 这里忽略
115 | 'comma-dangle': [0, 'always'],
116 | },
117 | }
118 |
--------------------------------------------------------------------------------
/react-base-webpack/config/eslintrc.conf.js:
--------------------------------------------------------------------------------
1 | /**
2 | * eslint规则配置,用于被业务工程引用
3 | * Created by zdliuccit on 2018/11/1.
4 | */
5 |
6 | module.exports = {
7 | root: true,
8 | env: {
9 | // 环境定义了预定义的全局变量。
10 | browser: true,
11 | node: true,
12 | es6: true,
13 | mocha: true
14 | },
15 | parser: 'babel-eslint',
16 | parserOptions: {
17 | // ECMAScript 版本
18 | ecmaVersion: 6,
19 | sourceType: 'module',
20 | },
21 | extends: 'standard',
22 | plugins: [
23 | 'html',
24 | 'import',
25 | 'promise',
26 | ],
27 | // add your custom rules here 0忽略 1warn 2 error
28 | rules: {
29 | // 缩进4空格 禁用2
30 | 'indent': [1, 2],
31 | // 禁止条件表达式中出现赋值操作符
32 | 'no-cond-assign': 2,
33 | // 允许console语句
34 | 'no-console': 1,
35 | // 允许 debugger
36 | 'no-debugger': 1,
37 | // var声明
38 | 'no-var': 2,
39 | // 禁止 function 定义中出现重名参数
40 | 'no-dupe-args': 2,
41 | // 禁止重复的函数声明
42 | 'no-func-assign': 2,
43 | // 忽略分号;
44 | 'semi': [1, 'never'],
45 | // 使用 === 和 !==
46 | 'eqeqeq': [2, 'allow-null'],
47 | // warn alert、
48 | 'no-alert': 1,
49 | // 禁用 eval()
50 | 'no-eval': 2,
51 | // 禁用 with 语句
52 | 'no-with': 2,
53 | // 要求或禁止使用严格模式指令
54 | 'strict': 2,
55 | // 要求或禁止 var 声明中的初始化(初值)
56 | 'init-declarations': 2,
57 | // 不允许 catch 子句的参数与外层作用域中的变量同名
58 | 'no-catch-shadow': 0,
59 | // 禁止删除变量
60 | 'no-delete-var': 2,
61 | // 不允许标签与变量同名
62 | 'no-label-var': 2,
63 | // 禁用特定的全局变量
64 | 'no-restricted-globals': 2,
65 | // 禁止 var 声明 与外层作用域的变量同名
66 | 'no-shadow': 0,
67 | // 禁止覆盖受限制的标识符
68 | 'no-shadow-restricted-names': 2,
69 | // 禁用未声明的变量,除非它们在 /*global */ 注释中被提到
70 | 'no-undef': 2,
71 | // 禁止将变量初始化为 undefined
72 | 'no-undef-init': 2,
73 | // 禁止将 undefined 作为标识符
74 | 'no-undefined': 2,
75 | // 禁止出现未使用过的变量
76 | 'no-unused-vars': [1, { 'vars': 'all', 'args': 'none' }],
77 | // 不允许在变量定义之前使用它们
78 | 'no-use-before-define': 1,
79 | // 强制一行的最大长度
80 | 'max-len': [1, 160],
81 | // 文件末尾强制换行
82 | 'eol-last': 0,
83 | // 强制使用单引号
84 | 'quotes': [2, 'single'],
85 | // 禁止修改 const 声明的变量
86 | 'no-const-assign': 2,
87 | // 禁止标识符中有悬空下划线_bar,这里忽略
88 | 'no-underscore-dangle': 0,
89 | // 禁用行尾空格
90 | 'no-trailing-spaces': 2,
91 | // 禁用不必要的嵌套块
92 | 'no-lone-blocks': 2,
93 | // 强制在 JSX 属性中一致地使用双引号或单引号
94 | 'jsx-quotes': 0,
95 | // 函数定义时括号前面要不要有空格
96 | 'space-before-function-paren': [1, `never`],
97 | //对象字面量项尾不能有逗号 这里忽略
98 | 'comma-dangle': [0, 'always'],
99 | // 在对象字面量属性中实现键和值之间的一致间隔 {key: value}
100 | 'key-spacing': [1, { 'mode': 'strict' }],
101 | // 允许对象所有键和值在同一行上
102 | 'object-property-newline': [0, { 'allowMultiplePropertiesPerLine': true }],
103 | // promise reject 参数设置为 * 任意类型
104 | 'prefer-promise-reject-errors': [0, { 'allowEmptyReject': true }]
105 | },
106 | }
107 |
--------------------------------------------------------------------------------
/webpack4-basic-config/src/utils/storage/README.md:
--------------------------------------------------------------------------------
1 | # x-vuex-storage
2 |
3 | 基于 vuex 的数据存储栈
4 |
5 | ## GET STARTED
6 |
7 | 安装所依赖的包
8 | ```bash
9 | npm i
10 | ```
11 |
12 | 启动服务用于查看 demo
13 | ```bash
14 | npm start
15 | ```
16 |
17 | ## USAGE
18 |
19 | 在最开始的时候请用以下方式实例化此方法
20 | ```javascript
21 | import vueStorage from './utils/storage'
22 | import Vue from 'vue'
23 | import VueRouter from 'vue-router'
24 |
25 | const router = new VueRouter(...)
26 |
27 | /**
28 | * @param {Object} Vue Vue
29 | * @param {router} [router=undefined] VueRouter 实例化对象
30 | * @param {array} [whiteList=[]] 路由白名单
31 | * @param {Function} cb 回调函数 函数内返回 Promise
32 | * 函数的返回参数有:
33 | * $storage -- VuexStorage 的对象
34 | * to -- router beforeEach 的 to
35 | * from -- router beforeEach 的 from
36 | */
37 | const store = VuexStorage(Vue, router, whiteList, ($storage, to, from) => Promise.resolve())
38 |
39 | new Vue({
40 | el: '#app',
41 | router,
42 | store,
43 | render: h => h(App)
44 | })
45 | ```
46 |
47 | 暴露在原型链上的对象为
48 | ```javascript
49 | this.$storage
50 | ```
51 |
52 | 此对象的属性为
53 | ```javascript
54 | // 为路由白名单,传入一个数组
55 | this.$storage.whiteList
56 | ```
57 |
58 | # :warning:警告
59 | ### 每一个方法中注意 isTemp 这个参数
60 | ### 默认为 true 用于存放至临时仓库会在每次路由变更且不为白名单的路径时清空此仓库
61 | ### 如果将手动变为 false 将会存放至永久仓库,只会在页面物理刷新和新开页面时清空
62 |
63 | 此对象的方法分别为
64 |
65 | ```javascript
66 | /**
67 | * 存储一项到仓库
68 | * @method setItem
69 | * @param {string|Array} key 需要存储的键
70 | * @param {any} value 需要存储的值
71 | * @param {boolean} [isTemp=true] 是否存储到临时的仓库
72 | */
73 | this.$storage.setItem(key, value, isTemp)
74 |
75 | /**
76 | * 用于快速增加 item 列表和更新白名单
77 | * 此方法在使用时会自动将对象和数组自动赋值给· items 的 value
78 | * 但是用值类型的变量需要在手动使用 getItem 获取
79 | * @method hyperChannel
80 | * @param {Array} [whiteList=[]] 路由白名单
81 | * @param {boolean} [isTemp=true] 是否存储到临时的仓库,默认为 true
82 | * @param {RestObejct} items rest 风格 item 列表
83 | */
84 | this.$storage.hyperChannel(whiteList = [], isTemp = true, ...items)
85 |
86 | /**
87 | * 删除指定的一项
88 | * @method removeItem
89 | * @param {string|Array} key 仓库中的键
90 | * @param {boolean} [isTemp=true] 是否删除临时的仓库
91 | */
92 | this.$storage.removeItem(key, isTemp)
93 |
94 | /**
95 | * 重置指定项
96 | * @method resetItem
97 | * @param {string|Array} key 仓库中的键
98 | * @param {boolean} [isTemp=true] 是否删除临时的仓库
99 | */
100 | this.$storage.resetItem(key, isTemp)
101 |
102 | /**
103 | * 清除所有
104 | * @method clear
105 | * @param {boolean} [isTemp=true] 是否清楚临时的仓库
106 | */
107 | this.$storage.clear(isTemp)
108 | /**
109 | * 更新指定项
110 | * @method updateItem
111 | * @param {string|Array} key 仓库中的键
112 | * @param {any} value 需要修改的值
113 | * @param {boolean} [isTemp=true] 是否存储到临时的仓库
114 | */
115 | this.$storage.updateItem(key, value, isTemp)
116 |
117 | /**
118 | * 获取仓库中的指定值
119 | * @method getItem
120 | * @param {string|Array} key 仓库中的键
121 | * @param {boolean} [isTemp=true] 是否存储到临时的仓库
122 | * @return {any} 仓库中存储的值
123 | */
124 | this.$storage.getItem(key, isTemp)
125 | ```
--------------------------------------------------------------------------------
/webpack4-ssr-config/config/eslintrc.conf.js:
--------------------------------------------------------------------------------
1 | /**
2 | * eslint规则配置,用于被业务工程引用
3 | * Created by liuzhengdong on 2018/4/3.
4 | */
5 |
6 | module.exports = {
7 | root: true,
8 | env: {
9 | // 环境定义了预定义的全局变量。
10 | browser: true,
11 | node: true,
12 | es6: true,
13 | mocha: true
14 | },
15 | parser: 'babel-eslint',
16 | parserOptions: {
17 | // ECMAScript 版本
18 | ecmaVersion: 6,
19 | sourceType: 'module',
20 | },
21 | extends: 'standard',
22 | plugins: [
23 | 'html',
24 | 'import',
25 | 'promise',
26 | ],
27 | // add your custom rules here 0忽略 1warn 2 error
28 | rules: {
29 | // 缩进4空格 禁用2 忽悠注释部分
30 | 'indent': [1, 2, { "ignoreComments": true }],
31 | // 禁止条件表达式中出现赋值操作符
32 | 'no-cond-assign': 2,
33 | // 允许console语句
34 | 'no-console': 1,
35 | // 允许 debugger
36 | 'no-debugger': 1,
37 | // var声明
38 | 'no-var': 2,
39 | // 禁止 function 定义中出现重名参数
40 | 'no-dupe-args': 2,
41 | // 禁止重复的函数声明
42 | 'no-func-assign': 2,
43 | // 忽略分号;
44 | 'semi': [1, 'never'],
45 | // 使用 === 和 !==
46 | 'eqeqeq': [2, 'allow-null'],
47 | // warn alert、
48 | 'no-alert': 1,
49 | // 禁用 eval()
50 | 'no-eval': 2,
51 | // 禁用 with 语句
52 | 'no-with': 2,
53 | // 要求或禁止使用严格模式指令
54 | 'strict': 2,
55 | // 要求或禁止 var 声明中的初始化(初值)
56 | 'init-declarations': 2,
57 | // 不允许 catch 子句的参数与外层作用域中的变量同名
58 | 'no-catch-shadow': 0,
59 | // 禁止删除变量
60 | 'no-delete-var': 2,
61 | // 不允许标签与变量同名
62 | 'no-label-var': 2,
63 | // 禁用特定的全局变量
64 | 'no-restricted-globals': 2,
65 | // 禁止 var 声明 与外层作用域的变量同名
66 | 'no-shadow': 0,
67 | // 禁止覆盖受限制的标识符
68 | 'no-shadow-restricted-names': 2,
69 | // 禁用未声明的变量,除非它们在 /*global */ 注释中被提到
70 | 'no-undef': 2,
71 | // 禁止将变量初始化为 undefined
72 | 'no-undef-init': 2,
73 | // 禁止将 undefined 作为标识符
74 | 'no-undefined': 2,
75 | // 禁止出现未使用过的变量
76 | 'no-unused-vars': [1, { 'vars': 'all', 'args': 'none' }],
77 | // 不允许在变量定义之前使用它们
78 | 'no-use-before-define': 1,
79 | // 强制一行的最大长度
80 | 'max-len': [1, 160],
81 | // 文件末尾强制换行
82 | 'eol-last': 0,
83 | // 强制使用单引号
84 | 'quotes': [2, 'single'],
85 | // 禁止修改 const 声明的变量
86 | 'no-const-assign': 2,
87 | // 禁止标识符中有悬空下划线_bar,这里忽略
88 | 'no-underscore-dangle': 0,
89 | // 禁用行尾空格
90 | 'no-trailing-spaces': 2,
91 | // 禁用不必要的嵌套块
92 | 'no-lone-blocks': 2,
93 | // 强制在 JSX 属性中一致地使用双引号或单引号
94 | 'jsx-quotes': 0,
95 | // 函数定义时括号前面要不要有空格
96 | 'space-before-function-paren': [1, `never`],
97 | //对象字面量项尾不能有逗号 这里忽略
98 | 'comma-dangle': [0, 'always'],
99 | // 在对象字面量属性中实现键和值之间的一致间隔 {key: value}
100 | 'key-spacing': [1, { 'mode': 'strict' }],
101 | // 允许对象所有键和值在同一行上
102 | 'object-property-newline': [0, { 'allowMultiplePropertiesPerLine': true }],
103 | // promise reject 参数设置为 * 任意类型
104 | 'prefer-promise-reject-errors': [0, { 'allowEmptyReject': true }]
105 | },
106 | }
107 |
--------------------------------------------------------------------------------
/webpack4-basic-config/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "webpack4-basic-config",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "start": "rimraf dist && npm run dll && cross-env NODE_ENV=development node config/index.js",
8 | "build": "rimraf dist && npm run dll && npm run prod",
9 | "dll": "webpack --progress --hide-modules --config config/webpack.config.dll.js",
10 | "prod": "cross-env NODE_ENV=production webpack --config config/webpack.config.prod.js --progress --hide-modules",
11 | "fix": "eslint src --ext .js,.vue --fix",
12 | "test": "echo \"Error: no test specified\" && exit 1"
13 | },
14 | "keywords": [
15 | "Vue",
16 | "Webpack",
17 | "Koa2",
18 | "Koa"
19 | ],
20 | "author": "zdliuccit",
21 | "license": "ISC",
22 | "dependencies": {
23 | "vue": "2.5.20",
24 | "vue-router": "3.0.2",
25 | "vuex": "3.0.1"
26 | },
27 | "devDependencies": {
28 | "@babel/core": "7.2.0",
29 | "@babel/plugin-syntax-dynamic-import": "7.2.0",
30 | "@babel/plugin-syntax-jsx": "7.2.0",
31 | "@babel/polyfill": "7.0.0",
32 | "@babel/preset-env": "7.2.0",
33 | "autoprefixer": "9.4.2",
34 | "axios": "0.18.0",
35 | "babel-eslint": "10.0.1",
36 | "babel-helper-vue-jsx-merge-props": "2.0.3",
37 | "babel-loader": "8.0.4",
38 | "babel-plugin-transform-vue-jsx": "4.0.1",
39 | "case-sensitive-paths-webpack-plugin": "2.1.2",
40 | "cross-env": "5.2.0",
41 | "css-loader": "1.0.0",
42 | "cssnano": "4.1.4",
43 | "element-ui": "^2.4.11",
44 | "eslint": "5.6.1",
45 | "eslint-config-standard": "12.0.0",
46 | "eslint-friendly-formatter": "4.0.1",
47 | "eslint-loader": "2.1.1",
48 | "eslint-plugin-html": "4.0.6",
49 | "eslint-plugin-import": "2.14.0",
50 | "eslint-plugin-node": "7.0.1",
51 | "eslint-plugin-promise": "4.0.1",
52 | "eslint-plugin-standard": "4.0.0",
53 | "extract-css-chunks-webpack-plugin": "3.2.1",
54 | "file-loader": "2.0.0",
55 | "friendly-errors-webpack-plugin": "1.7.0",
56 | "html-webpack-plugin": "3.2.0",
57 | "ip": "1.1.5",
58 | "json-loader": "0.5.7",
59 | "koa": "2.6.2",
60 | "koa-better-http-proxy": "0.2.4",
61 | "koa-compress": "2.0.0",
62 | "koa-convert": "1.2.0",
63 | "koa-logger": "3.2.0",
64 | "koa-router": "7.4.0",
65 | "koa-static": "5.0.0",
66 | "koa-webpack-dev-middleware": "2.0.2",
67 | "koa-webpack-hot-middleware": "1.0.3",
68 | "opn": "5.4.0",
69 | "optimize-css-assets-webpack-plugin": "5.0.1",
70 | "postcss": "7.0.6",
71 | "postcss-loader": "3.0.0",
72 | "postcss-pxtorem": "4.0.1",
73 | "progressbar.js": "^1.0.1",
74 | "stylus": "0.54.5",
75 | "stylus-loader": "3.0.2",
76 | "url-loader": "1.1.2",
77 | "vue-loader": "15.4.2",
78 | "vue-style-loader": "4.1.2",
79 | "vue-template-compiler": "2.5.20",
80 | "webpack": "4.27.1",
81 | "webpack-cli": "3.1.2",
82 | "webpack-dev-middleware": "3.4.0",
83 | "webpack-hot-middleware": "2.24.3",
84 | "webpack-merge": "4.1.5",
85 | "winston": "2.3.1"
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/webpack4-basic-config/config/eslintrc.conf.js:
--------------------------------------------------------------------------------
1 | /**
2 | * eslint规则配置,用于被业务工程引用
3 | * Created by liuzhengdong on 2018/4/3.
4 | */
5 |
6 | module.exports = {
7 | root: true,
8 | env: {
9 | // 环境定义了预定义的全局变量。
10 | browser: true,
11 | node: true,
12 | es6: true,
13 | mocha: true
14 | },
15 | parser: 'babel-eslint',
16 | parserOptions: {
17 | // ECMAScript 版本
18 | ecmaVersion: 6,
19 | sourceType: 'module',
20 | },
21 | extends: 'standard',
22 | plugins: [
23 | 'html',
24 | 'import',
25 | 'promise',
26 | ],
27 | // add your custom rules here 0忽略 1warn 2 error
28 | rules: {
29 | // 缩进4空格 禁用2 忽悠注释部分
30 | 'indent': [1, 2, {'ignoreComments': true}],
31 | // 禁止条件表达式中出现赋值操作符
32 | 'no-cond-assign': 2,
33 | // 允许console语句
34 | 'no-console': 1,
35 | // 允许 debugger
36 | 'no-debugger': 1,
37 | // var声明
38 | 'no-var': 2,
39 | // 禁止 function 定义中出现重名参数
40 | 'no-dupe-args': 2,
41 | // 禁止重复的函数声明
42 | 'no-func-assign': 2,
43 | // 忽略分号;
44 | 'semi': [1, 'never'],
45 | // 使用 === 和 !==
46 | 'eqeqeq': [2, 'allow-null'],
47 | // warn alert、
48 | 'no-alert': 1,
49 | // 禁用 eval()
50 | 'no-eval': 2,
51 | // 禁用 with 语句
52 | 'no-with': 2,
53 | // 要求或禁止使用严格模式指令
54 | 'strict': 2,
55 | // 要求或禁止 var 声明中的初始化(初值)
56 | 'init-declarations': 2,
57 | // 不允许 catch 子句的参数与外层作用域中的变量同名
58 | 'no-catch-shadow': 0,
59 | // 禁止删除变量
60 | 'no-delete-var': 2,
61 | // 不允许标签与变量同名
62 | 'no-label-var': 2,
63 | // 禁用特定的全局变量
64 | 'no-restricted-globals': 2,
65 | // 禁止 var 声明 与外层作用域的变量同名
66 | 'no-shadow': 0,
67 | // 禁止覆盖受限制的标识符
68 | 'no-shadow-restricted-names': 2,
69 | // 禁用未声明的变量,除非它们在 /*global */ 注释中被提到
70 | 'no-undef': 2,
71 | // 禁止将变量初始化为 undefined
72 | 'no-undef-init': 2,
73 | // 禁止将 undefined 作为标识符
74 | 'no-undefined': 2,
75 | // 禁止出现未使用过的变量
76 | 'no-unused-vars': [1, {'vars': 'all', 'args': 'none'}],
77 | // 不允许在变量定义之前使用它们
78 | 'no-use-before-define': 1,
79 | // 强制一行的最大长度
80 | 'max-len': [1, 160],
81 | // 文件末尾强制换行
82 | 'eol-last': 0,
83 | // 强制使用单引号
84 | 'quotes': [2, 'single'],
85 | // 禁止修改 const 声明的变量
86 | 'no-const-assign': 2,
87 | // 禁止标识符中有悬空下划线_bar,这里忽略
88 | 'no-underscore-dangle': 0,
89 | // 禁用行尾空格
90 | 'no-trailing-spaces': 2,
91 | // 禁用不必要的嵌套块
92 | 'no-lone-blocks': 2,
93 | // 强制在 JSX 属性中一致地使用双引号或单引号
94 | 'jsx-quotes': 0,
95 | // 函数定义时括号前面要不要有空格
96 | 'space-before-function-paren': [1, `never`],
97 | //对象字面量项尾不能有逗号 这里忽略
98 | 'comma-dangle': [0, 'always'],
99 | // 在对象字面量属性中实现键和值之间的一致间隔 {key: value}
100 | 'key-spacing': [1, {'mode': 'strict'}],
101 | // 允许对象所有键和值在同一行上
102 | 'object-property-newline': [0, {'allowMultiplePropertiesPerLine': true}],
103 | // promise reject 参数设置为 * 任意类型
104 | 'prefer-promise-reject-errors': [0, {'allowEmptyReject': true}],
105 | 'object-curly-spacing': ['error', 'never', {'objectsInObjects': true}]
106 | },
107 | }
108 |
--------------------------------------------------------------------------------
/webpack4-ssr-config/config/middle/proxyMiddleWare.js:
--------------------------------------------------------------------------------
1 | /**
2 | * http代理中间件 匹配代理、请求重定向
3 | * 获取app.config.js配置文件,匹配proxy
4 | */
5 | const urlUtils = require('url')
6 | const koaHttpProxy = require('koa-better-http-proxy')
7 | const compose = require('koa-compose')
8 | const appConfig = require('./../../app.config')
9 | const logger = require('./../logger/koa-logger')('proxyMiddleWare')
10 |
11 | const isProd = process.env.NODE_ENV === 'production'
12 |
13 | /**
14 | * 代理处理中间件
15 | * @return {Function} koa middleware
16 | */
17 | module.exports = function () {
18 | async function preProxyMiddleware(ctx, next) {
19 | const url = ctx.url
20 | // logger.info(`Request '${url}'`)
21 | let proxyTarget
22 | let proxyConfig = appConfig.proxy
23 | // 在appConfig.proxy中寻找匹配前缀的代理
24 | for (const [prefix, target] of Object.entries(proxyConfig)) {
25 | if (url.startsWith(prefix)) {
26 | // 匹配替换
27 | ctx.url = url.replace(prefix, '')
28 | proxyTarget = target
29 | ctx._proxyTarget = proxyTarget
30 | logger.info(`Match to proxy: '${prefix}' => '${proxyTarget}'`)
31 | break
32 | }
33 | }
34 | if (!proxyTarget) {
35 | logger.info('Proxy not found')
36 | return Promise.resolve()
37 | }
38 | logger.info(`Will be Agent to '${proxyTarget + ctx.url}'`)
39 | return next()
40 | }
41 |
42 | /**
43 | * 顺序执行async函数
44 | */
45 | return compose([
46 | preProxyMiddleware,
47 | koaHttpProxy(
48 | (ctx) => {
49 | return ctx._proxyTarget
50 | },
51 | {
52 | // 不解析body,不限制body大小
53 | parseReqBody: false,
54 | /**
55 | * 发出代理请求前的回调,更改头文件
56 | * @param {Object} proxyReqOpts - 代理请求选项
57 | * @param {ctx} ctx - koa ctx
58 | * @return {Promise.<*>} *
59 | */
60 | async proxyReqOptDecorator(proxyReqOpts, ctx) {
61 | const parsedTarget = urlUtils.parse(ctx._proxyTarget, true)
62 | proxyReqOpts.host = parsedTarget.hostname
63 | proxyReqOpts.port = parsedTarget.port
64 | proxyReqOpts.https = parsedTarget.protocol === 'https:'
65 |
66 | // 去掉Referer头,否则可能会造成CSRF问题,影响开发
67 | if (!isProd) {
68 | delete proxyReqOpts.headers.Referer
69 | delete proxyReqOpts.headers.Origin
70 | }
71 | // 计时开始
72 | ctx._proxyStartTime = Date.now()
73 | return proxyReqOpts
74 | },
75 | /**
76 | * 代理请求被响应后的回调
77 | * @param {Response} proxyRes - 代理请求选项
78 | * @param {Object} proxyResData - 响应数据
79 | * @param {ctx} ctx - koa ctx
80 | * @return {Promise.<*>} *
81 | */
82 | async userResDecorator(proxyRes, proxyResData, ctx) {
83 | // logger.info('ProxyRes headers:', '\n', JSON.stringify(ctx.response.headers, null, 2))
84 | const location = `${ctx._proxyTarget}${ctx.url}`
85 | logger.info(`Proxy request '${location}' completed(${proxyRes.statusCode}), costing ${Date.now() - ctx._proxyStartTime}ms.`)
86 | return proxyResData
87 | },
88 | }),
89 | ])
90 | }
91 |
--------------------------------------------------------------------------------
/webpack3-basic-config/doc/npm包说明.md:
--------------------------------------------------------------------------------
1 | NPM包说明
2 |
3 | * `koa`
4 | * `koa-static`和`koa-view` 用于设置koa的静态文件目录和模板渲染
5 | * `koa-webpack-dev-middleware`和`koa-webpack-hot-middleware` 开发和热加载模块
6 | * `koa-convert` 将generator转成 async await异步中间件
7 | * `koa-compose` koa2不需要再借助于co这种工具库了,所以有了koa-compose
8 | * `koa-better-http-proxy` Koa中间件代理请求到另一个主机并通过响应
9 | * `url` This module has utilities for URL resolution and parsing meant to have feature parity with node.js core url module.
10 |
11 | * vue
12 | * vue-router
13 | * autoprefixer // css兼容性,对不同的浏览器加上前缀
14 | * opn // 打开指定浏览器
15 | * axios 用于浏览器和node.js的基于Promise的HTTP客户端
16 | * ora 优雅的终端旋转器
17 | * cross-env 运行跨平台设置和使用环境变量的脚本
18 | * `Lodash`这是一个具有一致接口、模块化、高性能等特性的 JavaScript 工具库
19 |
20 | * `babel-core`
21 | ---
22 | 如果你需要以编程的方式来使用 Babel,可以使用 babel-core 这个包。
23 | babel-core 的作用是把 js 代码分析成 ast ,方便各个插件分析语法进行相应的处理。有些新语法在低版本 js 中是不存在的,
24 | 如箭头函数,rest 参数,函数默认值等,这种语言层面的不兼容只能通过将代码转为 ast,分析其语法后再转为低版本 js。首先安装 babel-core。
25 | 还可以通过babel-register和babel-node使用Babel,但由于这两种用法不适合生产环境故省略。
26 |
27 | * `babel-preset-es2015` 打包了 es6 的特性
28 | * `babel-preset-latest`
29 | latest是一个特殊的presets,包括了es2015,es2016,es2017的插件(目前为止,以后有es2018也会包括进去)。
30 | 即总是包含最新的编译插件。
31 | * `babel-preset-env`
32 | 上面提到的各种preset的问题就是: 它们都太”重”了, 即包含了过多在某些情况下不需要的功能. 比如,
33 | 现代的浏览器大多支持ES6的generator, 但是如果你使用babel-preset-es2015,
34 | 它会将generator函数编译为复杂的ES5代码, 这是没有必要的。但使用babel-preset-env, 我们可以声明环境, 然后该preset就会只编译包含我们所声明环境缺少的特性的代码,因此也是比较推荐的方式。
35 | ```json
36 | {
37 | "presets": ["env"]
38 | }
39 |
40 | ```
41 | * `babel-preset-stage-0` 打包处于 strawman 阶段的语法 0、1、2、3总共4个阶段
42 | * `babel-polyfill` 代码填充,也可译作兼容性补丁, 文件顶部引入就行,import "babel-polyfill";
43 | * `babel-plugin-transform-runtime` 和 `babel-runtime` 功能和`babel-polyfill`一样
44 | ```js
45 | // 你不介意污染全局变量 用 babel-polyfill
46 | // 写模块,为了避免污染使用者的环境 只能用 babel-runtime + babel-plugin-transform-runtime。
47 | ```
48 | * `babel-loader`
49 | * `babel-eslint`
50 |
51 |
52 | * `extract-text-webpack-plugin` 抽离js中的css样式
53 | * `url-loader`、`file-loader`打包文件和图片 url-loader是对file-loader的上层封装,比如webpack中对图片的加载器配置
54 | ```js
55 | {test: /\.(png|jpg)$/, loader: 'url-loader?limit=8192'}
56 | //一般限制小图片转 base64 可以用 url-loader,其他情况都用 file-loader。
57 | ```
58 | * `json-loader`
59 | * `vue-loader`
60 | * `style-loader` 样式装载机 通过注入
--------------------------------------------------------------------------------
/webpack3-basic-config/config/utils/proxyMiddleWare.js:
--------------------------------------------------------------------------------
1 | /**
2 | * http代理中间件 匹配代理、请求重定向
3 | * 获取app.config.js配置文件,匹配proxy
4 | */
5 | const path = require('path')
6 | const urlUtils = require('url')
7 | const koaHttpProxy = require('koa-better-http-proxy')
8 | const compose = require('koa-compose')
9 | const appConfig = require('./../../app.config')
10 | const { IS_DEBUG } = require('./env')
11 | const logger = require('./logger/koa-logger')('proxyMiddleWare')
12 |
13 | const needToken = !!appConfig.token
14 | let tokenManager
15 | if (needToken) {
16 | tokenManager = require('./token')(appConfig.token)
17 | }
18 |
19 | /**
20 | * 获取代理配置
21 | * @return {*} 代理配置
22 | */
23 | function getProxyConfig () {
24 | // 开发模式每次重新读取
25 | if (!IS_DEBUG) {
26 | return appConfig.proxy
27 | }
28 | // 生产环境读取
29 | const serverConfig = require(path.join(process.cwd(), 'server.config.js'))
30 | return serverConfig.proxy
31 | }
32 |
33 | /**
34 | * 代理处理中间件
35 | * @return {Function} koa middleware
36 | */
37 | module.exports = function () {
38 | async function preProxyMiddleware (ctx, next) {
39 | const url = ctx.url
40 | logger.info(`Request '${url}'`)
41 | let proxyTarget
42 | let proxyConfig = getProxyConfig()
43 | // 在appConfig.proxy中寻找匹配前缀的代理
44 | for (const [prefix, target] of Object.entries(proxyConfig)) {
45 | if (url.startsWith(prefix)) {
46 | // 匹配替换
47 | if (!IS_DEBUG) {
48 | ctx.url = url.replace(prefix, '')
49 | }
50 | proxyTarget = target
51 | ctx._proxyTarget = proxyTarget
52 |
53 | logger.info(`Match to proxy: '${prefix}' => '${proxyTarget}'`)
54 | break
55 | }
56 | }
57 | if (!proxyTarget) {
58 | logger.info('Proxy not found, skipped')
59 | return Promise.resolve()
60 | }
61 | logger.info(`Will be Agent to '${proxyTarget + ctx.url}'`)
62 | return next()
63 | }
64 |
65 | /**
66 | * 顺序执行async函数
67 | */
68 | return compose([
69 | preProxyMiddleware,
70 | koaHttpProxy(
71 | (ctx) => {
72 | return ctx._proxyTarget
73 | },
74 | {
75 | // 不解析body,不限制body大小
76 | parseReqBody: false,
77 | /**
78 | * 发出代理请求前的回调,更改头文件
79 | * @param {Object} proxyReqOpts - 代理请求选项
80 | * @param {ctx} ctx - koa ctx
81 | * @return {Promise.<*>} *
82 | */
83 | async proxyReqOptDecorator (proxyReqOpts, ctx) {
84 | const parsedTarget = urlUtils.parse(ctx._proxyTarget, true)
85 | proxyReqOpts.host = parsedTarget.hostname
86 | proxyReqOpts.port = parsedTarget.port
87 | proxyReqOpts.https = parsedTarget.protocol === 'https:'
88 |
89 | // 去掉Referer头,否则可能会造成CSRF问题,影响开发
90 | if (IS_DEBUG) {
91 | delete proxyReqOpts.headers.Referer
92 | delete proxyReqOpts.headers.Origin
93 | }
94 | // 计时开始
95 | ctx._proxyStartTime = Date.now()
96 | if (!needToken) {
97 | return proxyReqOpts
98 | }
99 | return await tokenManager.handleRequest(ctx)
100 | .then((additionalHeaders) => {
101 | Object.assign(proxyReqOpts.headers, additionalHeaders)
102 | })
103 | .then(() => {
104 | return proxyReqOpts
105 | })
106 | },
107 | /**
108 | * 代理请求被响应后的回调
109 | * @param {Response} proxyRes - 代理请求选项
110 | * @param {Object} proxyResData - 响应数据
111 | * @param {ctx} ctx - koa ctx
112 | * @return {Promise.<*>} *
113 | */
114 | async userResDecorator (proxyRes, proxyResData, ctx) {
115 | logger.info('ProxyRes headers:', '\n', JSON.stringify(ctx.response.headers, null, 2))
116 | const location = `${ctx._proxyTarget}${ctx.url}`
117 | logger.info(`Proxy request '${location}' completed(${proxyRes.statusCode}), costing ${Date.now() - ctx._proxyStartTime}ms.`)
118 | if (!needToken) {
119 | return proxyResData
120 | }
121 | return await tokenManager.handleResponse(ctx)
122 | .then(() => {
123 | return proxyResData
124 | })
125 | },
126 | }),
127 | ])
128 | }
129 |
--------------------------------------------------------------------------------
/webpack4-basic-config/config/utils/proxyMiddleWare.js:
--------------------------------------------------------------------------------
1 | /**
2 | * http代理中间件 匹配代理、请求重定向
3 | * 获取app.config.js配置文件,匹配proxy
4 | */
5 | const path = require('path')
6 | const urlUtils = require('url')
7 | const koaHttpProxy = require('koa-better-http-proxy')
8 | const compose = require('koa-compose')
9 | const appConfig = require('./../../app.config')
10 | const { IS_DEBUG } = require('./env')
11 | const logger = require('./logger/koa-logger')('proxyMiddleWare')
12 |
13 | const needToken = !!appConfig.token
14 | let tokenManager
15 | if (needToken) {
16 | tokenManager = require('./token')(appConfig.token)
17 | }
18 |
19 | /**
20 | * 获取代理配置
21 | * @return {*} 代理配置
22 | */
23 | function getProxyConfig () {
24 | // 开发模式每次重新读取
25 | if (!IS_DEBUG) {
26 | return appConfig.proxy
27 | }
28 | // 生产环境读取
29 | const serverConfig = require(path.join(process.cwd(), 'server.config.js'))
30 | return serverConfig.proxy
31 | }
32 |
33 | /**
34 | * 代理处理中间件
35 | * @return {Function} koa middleware
36 | */
37 | module.exports = function () {
38 | async function preProxyMiddleware (ctx, next) {
39 | const url = ctx.url
40 | logger.info(`Request '${url}'`)
41 | let proxyTarget
42 | let proxyConfig = getProxyConfig()
43 | // 在appConfig.proxy中寻找匹配前缀的代理
44 | for (const [prefix, target] of Object.entries(proxyConfig)) {
45 | if (url.startsWith(prefix)) {
46 | // 匹配替换
47 | if (!IS_DEBUG) {
48 | ctx.url = url.replace(prefix, '')
49 | }
50 | proxyTarget = target
51 | ctx._proxyTarget = proxyTarget
52 |
53 | logger.info(`Match to proxy: '${prefix}' => '${proxyTarget}'`)
54 | break
55 | }
56 | }
57 | if (!proxyTarget) {
58 | logger.info('Proxy not found, skipped')
59 | return Promise.resolve()
60 | }
61 | logger.info(`Will be Agent to '${proxyTarget + ctx.url}'`)
62 | return next()
63 | }
64 |
65 | /**
66 | * 顺序执行async函数
67 | */
68 | return compose([
69 | preProxyMiddleware,
70 | koaHttpProxy(
71 | (ctx) => {
72 | return ctx._proxyTarget
73 | },
74 | {
75 | // 不解析body,不限制body大小
76 | parseReqBody: false,
77 | /**
78 | * 发出代理请求前的回调,更改头文件
79 | * @param {Object} proxyReqOpts - 代理请求选项
80 | * @param {ctx} ctx - koa ctx
81 | * @return {Promise.<*>} *
82 | */
83 | async proxyReqOptDecorator (proxyReqOpts, ctx) {
84 | const parsedTarget = urlUtils.parse(ctx._proxyTarget, true)
85 | proxyReqOpts.host = parsedTarget.hostname
86 | proxyReqOpts.port = parsedTarget.port
87 | proxyReqOpts.https = parsedTarget.protocol === 'https:'
88 |
89 | // 去掉Referer头,否则可能会造成CSRF问题,影响开发
90 | if (IS_DEBUG) {
91 | delete proxyReqOpts.headers.Referer
92 | delete proxyReqOpts.headers.Origin
93 | }
94 | // 计时开始
95 | ctx._proxyStartTime = Date.now()
96 | if (!needToken) {
97 | return proxyReqOpts
98 | }
99 | return await tokenManager.handleRequest(ctx)
100 | .then((additionalHeaders) => {
101 | Object.assign(proxyReqOpts.headers, additionalHeaders)
102 | })
103 | .then(() => {
104 | return proxyReqOpts
105 | })
106 | },
107 | /**
108 | * 代理请求被响应后的回调
109 | * @param {Response} proxyRes - 代理请求选项
110 | * @param {Object} proxyResData - 响应数据
111 | * @param {ctx} ctx - koa ctx
112 | * @return {Promise.<*>} *
113 | */
114 | async userResDecorator (proxyRes, proxyResData, ctx) {
115 | logger.info('ProxyRes headers:', '\n', JSON.stringify(ctx.response.headers, null, 2))
116 | const location = `${ctx._proxyTarget}${ctx.url}`
117 | logger.info(`Proxy request '${location}' completed(${proxyRes.statusCode}), costing ${Date.now() - ctx._proxyStartTime}ms.`)
118 | if (!needToken) {
119 | return proxyResData
120 | }
121 | return await tokenManager.handleResponse(ctx)
122 | .then(() => {
123 | return proxyResData
124 | })
125 | },
126 | }),
127 | ])
128 | }
129 |
--------------------------------------------------------------------------------
/webpack4-ssr-config/pm2.md:
--------------------------------------------------------------------------------
1 | # pm2
2 |
3 | #### 安装
4 |
5 | ```npm
6 | npm install pm2 -g // sudo
7 | ```
8 |
9 | #### 1、常用命令
10 |
11 | * pm2 start app.js # 启动,守护进程。自动重启应用程序,加环境变量,比如配置 env_pro --> 加 --env pro
12 | * pm restart # 重启
13 | * pm2 stop # 停止 参数 = id|name|all|json|stdin
14 | * pm2 delete| del # 删除 参数 = name|id|script|all|json|stdin
15 |
16 | #### 2、集群模式
17 |
18 | * pm2 start app.js -i 4 # 参数 = 数字|max 在集群模式下,启动4个应用程序实例 同时,将网络请求,负载均衡到每个应用实例
19 |
20 | * pm2 reload all # 0秒重启所有应用
21 |
22 | pm2 scale appName 10 # 将应用进程调整到10
23 |
24 | * pm2 reset appName # 重置所有计数器
25 |
26 | #### 3、 进程监控
27 |
28 | * pm2 list|ls # 列出所有用PM2启动的进程
29 | * pm2 monit # 显示每个应用占用的cpu和内存
30 | * pm2 show appName or id # 显示某个进程的所有信息
31 |
32 | #### 4、日志管理
33 |
34 | * pm2 logs # 显示所有应用的日志
35 |
36 | * pm2 logs appName # 显示某个应用的日志
37 |
38 | * pm2 logs --json # json化日志
39 |
40 | * pm2 flush # 刷新日志
41 |
42 | * pm2 reloadLogs # 重新加载所有日志
43 |
44 | #### 5、启动/引导管理
45 |
46 | * pm2 startup # 检测init系统,在启动时生成和配置pm2
47 | * pm2 save # 保存当前进程列表
48 | * pm2 resurrect # 恢复以前保存的进程。
49 | * pm2 unstartup # 停用和删除启动系统
50 | * pm2 update # 保存进程,终止PM2并恢复进程
51 | * pm2 generate # 生成样本json配置文件。
52 |
53 | #### 6、部署
54 |
55 | * pm2 deploy app.json prod setup # 设置“生产环境”远程服务器。
56 | * pm2 deploy app.json prod # 更新“生产环境”远程服务器。
57 | * pm2 deploy app.json prod revert 2 # 将“生产环境”远程服务器恢复2。
58 |
59 | #### 7、模块系统
60 |
61 | * pm2 module:generate [name] # 生成名称为[name]的示例模块。
62 | * pm2 install pm2-logrotate # 安装模块(这里是日志循环系统)。
63 | * pm2 uninstall pm2-logrotate # 卸载模块。
64 | * pm2 publish # 增量版本,git push和npm发布。
65 |
66 |
67 |
68 | options具有以下选项的对象(这些选项的其他说明在此处):
69 |
70 | - `name` - 可用于在其他命令中稍后与进程交互(例如,重新启动)的任意名称。默认为脚本名称,不带其扩展名(例如`"testScript"`for `"testScript.js"`)。
71 | - `script` - 要运行的脚本的路径。
72 | - `args` - 由传递给脚本的参数组成的字符串或字符串数组。
73 | - `interpreterArgs` - 由调用解释器进程的参数组成的字符串或字符串数组。例如“-harmony”或[“-harmony”,“ - debug”]。仅适用`interpreter`于“none”以外的其他内容(默认情况下为“节点”)。
74 | - `cwd` - 用于启动进程的工作目录。
75 | - `output`- (默认值`"~/.pm2/logs/app_name-out.log"`:)将stdout输出追加到的文件的路径。可以是同一个文件`error`。
76 | - `error`- (默认值`"~/.pm2/logs/app_name-error.err"`:)将stderr输出附加到的文件的路径。可以是同一个文件`output`。
77 | - `logDateFormat` - 日志时间戳的显示格式(例如“YYYY-MM-DD HH:mm Z”)。格式是[时刻显示格式](http://momentjs.com/docs/#/displaying/)。
78 | - `pid`- (默认值`"~/.pm2/pids/app_name-id.pid"`:)用于写入已启动进程的pid的文件的路径。该文件将被覆盖。请注意,pm2不会以任何方式使用该文件,因此用户可以随时自由操作或删除该文件。当进程停止或守护程序被终止时,将删除该文件。
79 | - `minUptime` - 脚本在成功启动之前的最短正常运行时间。
80 | - `maxRestarts`- 如果脚本以小于的速率退出,则将重新启动脚本的最大行数`min_uptime`。
81 | - `maxMemoryRestart`- 如果设置和`script`内存使用量与配置的数量有关,则pm2重新启动`script`。使用人性化的后缀:'K'表示千字节,“M”表示兆字节,“G”表示千兆字节等。例如“150M”。
82 | - killTimeout`- (默认值:)`1600`在`stop`或`restart`命令发出`SIGINT`信号以强制使用`SIGKILL`信号终止脚本之后等待的毫秒数。
83 | - `restartDelay`- (默认值`0`:)重新启动已退出的脚本之前等待的毫秒数。
84 | - `interpreter`- (默认值`'node'`:)脚本的解释器(例如“python”,“ruby”,“bash”等)。值“none”将执行“脚本”作为二进制可执行文件。
85 | - `execMode`- (默认值:) `'fork'`如果设置为'cluster',将启用群集(运行多个实例`script`)。[在这里看到更多的细节](http://pm2.keymetrics.io/docs/usage/cluster-mode/)。
86 | - `instances`- (*默认值1* :) `script`要创建的实例数。仅与`exec_mode`'集群' 相关。
87 | - `mergeLogs`- (默认值`false`:)如果为true,则将所有实例的日志文件合并`script`为一个stderr日志和一个stdout日志。仅适用于“群集”模式。例如,如果您通过pm2启动了4个'test.js'实例,通常会有4个stdout日志文件和4个stderr日志文件,但是如果将此选项设置为true,则只有一个stdout文件和一个stderr文件。
88 | - `watch`- 如果设置为`true`,则在更改`script`文件时将重新启动应用程序。
89 | - `force`(默认值`false`:)默认情况下,pm2仅在该脚本尚未运行时才启动脚本(脚本是应用程序的路径,而不是已运行的应用程序的名称)。如果`force`设置为true,则pm2将启动该脚本的新实例。
90 | - `autorestart`(默认`true`)。如果`false`,pm2 在成功完成或进程失败后将*不会*尝试重新启动它。
91 | - `cron`
92 | - `executeCommand`
93 | - `write`
94 | - `sourceMapSupport`
95 | - `disableSourceMapSupport`
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
--------------------------------------------------------------------------------
/webpack4-basic-config/config/webpack.config.base.js:
--------------------------------------------------------------------------------
1 | /**
2 | * webpack base配置
3 | * Created by zdliu on 2018/7/6.
4 | */
5 | const appConfig = require('./../app.config')
6 | const path = require('path')
7 | const webpack = require('webpack')
8 | const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin')
9 | const HtmlWebpackPlugin = require('html-webpack-plugin')
10 | const vueLoaderPlugin = require('vue-loader/lib/plugin')
11 | const ExtractCssChunks = require("extract-css-chunks-webpack-plugin")
12 | const merge = require('webpack-merge')
13 | const vendorsManifest = require(path.join(process.cwd(), 'vendors-manifest.json'))
14 |
15 | const isProd = process.env.NODE_ENV === 'production'
16 |
17 | // 版本号
18 | const appVersion = new Date().getTime()
19 |
20 | function resolve(dir) {
21 | return path.resolve(process.cwd(), dir)
22 | }
23 |
24 | // 网站图标
25 | const favicon = path.join(process.cwd(), 'favicon.ico')
26 |
27 | module.exports = function () {
28 | const config = merge(appConfig.webpack, {
29 | // 输出模块配置
30 | output: {
31 | // 输出到这个目录下
32 | path: resolve('dist'),
33 | // 生成的文件名, [name] 即为entry配置中的key
34 | filename: `[name].[${isProd ? 'chunkhash' : 'hash'}:8].js`,
35 | // 异步模块文件名
36 | chunkFilename: '[id].js',
37 | publicPath: '/'
38 | },
39 | // 寻找模块时的一些缺省设置
40 | resolve: {
41 | // 补充扩展名
42 | extensions: ['.js', '.vue', '.json'],
43 | // 别名,可以直接使用别名来代表设定的路径以及其他
44 | alias: {
45 | 'vue': 'vue/dist/vue.esm.js',
46 | '@': resolve('src'),
47 | '@config': resolve('config'),
48 | }
49 | },
50 | module: {
51 | rules: [
52 | {
53 | test: /\.vue$/,
54 | use: ['vue-loader', 'eslint-loader']
55 | },
56 | // js,jsx 转译
57 | {
58 | test: /\.(js|jsx)$/,
59 | use: ['babel-loader'],
60 | exclude: /node_modules/,
61 | },
62 | {
63 | test: /\.css$/,
64 | use: [isProd ? ExtractCssChunks.loader : 'vue-style-loader', 'css-loader', 'postcss-loader']
65 | },
66 | {
67 | test: /\.(styl|stylus)$/,
68 | use: [isProd ? ExtractCssChunks.loader : 'vue-style-loader', 'css-loader', 'postcss-loader',
69 | {
70 | loader: 'stylus-loader',
71 | options: isProd ? {} : {sourceMap: 'inline'}
72 | }
73 | ]
74 | },
75 | {
76 | test: /\.json$/,
77 | use: 'json-loader',
78 | },
79 | // 图片资源 gif|jpg|jpeg|png|bmp|svg|ico
80 | {
81 | test: /\.(gif|jpg|jpeg|png|bmp|svg|ico)(\?.*)?$/,
82 | use: [{
83 | loader: 'url-loader',
84 | options: {
85 | limit: 1,
86 | name: 'assets/images/[name].[hash:8].[ext]',
87 | },
88 | }],
89 | },
90 | // 字体文件 woff|woff2|eot|ttf
91 | {
92 | test: /\.(woff|woff2|eot|ttf)(\?.*)?$/,
93 | use: [{
94 | loader: 'url-loader',
95 | options: {
96 | // 小于8912字节的文件,返回dataurl
97 | limit: 8912,
98 | // 生成的文件名,[name]为原始文件名,[hash:8]为根据文件内容生成8位md5值,[ext]为原始文件扩展名
99 | name: 'assets/font/[name].[hash:8].[ext]',
100 | },
101 | }],
102 | },
103 | ],
104 | },
105 | performance: {
106 | maxEntrypointSize: 300000,
107 | hints: false
108 | },
109 | plugins: [
110 | // 由于mac不区分大小写,linux区分大小写,可能导致mac上正常,在部署时出错,所以强制区分大小写
111 | new CaseSensitivePathsPlugin(),
112 | // // 读取HTML模板文件,并输出HTML文件,开发环境实际输出到内存中
113 | new HtmlWebpackPlugin({
114 | appVersion,
115 | favicon,
116 | filename: 'index.html',
117 | dllSrc: `/${vendorsManifest.name}.dll.js`,
118 | template: path.join(process.cwd(), 'index.template.ejs'),
119 | inject: true,
120 | // minify: {
121 | // removeComments: true, //去注释
122 | // collapseWhitespace: true, //压缩空格
123 | // },
124 | }),
125 | new webpack.DllReferencePlugin({
126 | context: path.join(process.cwd()),
127 | manifest: path.join(process.cwd(), 'vendors-manifest.json'),
128 | }),
129 | new vueLoaderPlugin(),
130 | new webpack.optimize.LimitChunkCountPlugin({
131 | maxChunks: 1
132 | })
133 | ],
134 | })
135 | return config
136 | }
--------------------------------------------------------------------------------