From bf0019c7b88e7bca2987c7f9684c7670fe979a2c Mon Sep 17 00:00:00 2001 From: caoli Date: Wed, 28 Feb 2018 18:50:10 +0800 Subject: [PATCH] feat: dll and lib support --- .eslintignore | 3 +- README.md | 4 +- app/web/page/about/about.vue | 9 +- app/web/page/index/index.vue | 2 +- config/config.local.js | 4 + package.json | 10 +- script/postinstall.js | 6 + .../webpack-hot-middleware/middleware.js | 128 ++++++++++++++++++ webpack.config.js | 3 + 9 files changed, 151 insertions(+), 18 deletions(-) create mode 100644 script/postinstall.js create mode 100644 script/webpack4/webpack-hot-middleware/middleware.js diff --git a/.eslintignore b/.eslintignore index 52ee69be..749d86ef 100644 --- a/.eslintignore +++ b/.eslintignore @@ -13,4 +13,5 @@ app/web/store plugins/ app/web/asset/ app/view/ -test.js \ No newline at end of file +test.js +script/webpack4/ \ No newline at end of file diff --git a/README.md b/README.md index bf17caf0..996d8ce0 100755 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # egg-vue-webpack-boilerplate -基于 Egg + Vue + Webpack3/Webpack2 多页面和单页面服务端客户端渲染同构工程骨架项目. +基于 Egg + Vue + Webpack4 多页面和单页面服务端客户端渲染同构工程骨架项目. ## 纯净版 @@ -14,7 +14,7 @@ - Egg 版本: ^2.x.x - Node 版本: Node ^8.x.x+, Node 6.x.x 版本请见 [Egg 1.0 + Node6分支](https://github.com/hubcarl/egg-vue-webpack-boilerplate/tree/node6) -- Webpack 版本: ^3.8.1, 对应 `easywebpack-vue` 版本为 ^3.5.0 +- Webpack 版本: ^4.x.x, 对应 `easywebpack-vue` 版本为 ^4.x.x - Vue 版本: ^2.5.0 ## 说明 diff --git a/app/web/page/about/about.vue b/app/web/page/about/about.vue index 977f8d7a..43e1e36a 100644 --- a/app/web/page/about/about.vue +++ b/app/web/page/about/about.vue @@ -20,19 +20,12 @@ diff --git a/app/web/page/index/index.vue b/app/web/page/index/index.vue index b4ca324a..7ccf6ed5 100644 --- a/app/web/page/index/index.vue +++ b/app/web/page/index/index.vue @@ -16,7 +16,7 @@
  • Sky
  • -
  • +收藏
  • +
  • +收藏1111
  • {{item.summary}}
  • diff --git a/config/config.local.js b/config/config.local.js index 778cfa91..81d13ce6 100644 --- a/config/config.local.js +++ b/config/config.local.js @@ -20,6 +20,10 @@ module.exports = app => { injectCss: false }; + exports.webpack = { + webpackConfigList: require('easywebpack-vue').getWebpackConfig() + }; + const localIP = ip.address(); const domainWhiteList = []; [7001, 9000, 9001].forEach(port => { diff --git a/package.json b/package.json index c79d50de..07fc374e 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,7 @@ "version": "3.6.2", "description": "基于 easywebpack-vue 和 egg-view-vue-ssr插件的 egg + vue 服务端渲染同构工程骨架项目", "scripts": { + "postinstall": "node ./script/postinstall.js", "debug": "egg-bin debug", "build": "cross-env easywebpack build prod", "build:dev": "cross-env easywebpack build dev", @@ -23,8 +24,8 @@ "dependencies": { "axios": "^0.17.1", "cross-env": "^5.0.0", + "easywebpack": "^4.0.0-beta.7", "egg": "^2.1.0", - "egg-bin": "^4.3.7", "egg-cors": "^2.0.0", "egg-logger": "^1.5.0", "egg-validate": "^1.0.0", @@ -32,14 +33,12 @@ "element-ui": "^2.0.8", "extend": "~3.0.0", "lodash": "^4.17.4", - "mint-ui": "^2.2.9", - "mockjs": "^1.0.1-beta3", "moment": "^2.17.1", "server-side-render-resource": "^1.0.0", "vue": "^2.5.0", - "vue-hot-reload-api": "^2.1.0", "vue-router": "^3.0.1", "vue-server-renderer": "^2.5.3", + "vue-template-compiler": "^2.5.13", "vuex": "^3.0.1", "vuex-router-sync": "^5.0.0" }, @@ -54,12 +53,11 @@ "babel-plugin-transform-runtime": "^6.15.0", "babel-preset-env": "^1.6.0", "easywebpack-vue": "next", + "egg-bin": "^4.3.7", "egg-logview": "^1.0.0", "egg-webpack": "next", "egg-webpack-vue": "^2.0.0", - "eslint": "^4.3.0", "eslint-config-egg": "^5.0.0", - "eslint-loader": "^1.9.0", "eslint-plugin-vue": "^2.0.1", "ip": "^1.1.5", "less": "^2.7.2", diff --git a/script/postinstall.js b/script/postinstall.js new file mode 100644 index 00000000..a96e5803 --- /dev/null +++ b/script/postinstall.js @@ -0,0 +1,6 @@ +'use strict'; +const path = require('path'); +const fs = require('fs'); +const source = path.join(process.cwd(), 'script/webpack4/webpack-hot-middleware/middleware.js'); +const target = path.join(process.cwd(), 'node_modules/webpack-hot-middleware/middleware.js'); +fs.createReadStream(source).pipe(fs.createWriteStream(target)); \ No newline at end of file diff --git a/script/webpack4/webpack-hot-middleware/middleware.js b/script/webpack4/webpack-hot-middleware/middleware.js new file mode 100644 index 00000000..d7c1cebb --- /dev/null +++ b/script/webpack4/webpack-hot-middleware/middleware.js @@ -0,0 +1,128 @@ +module.exports = webpackHotMiddleware; + +var helpers = require('./helpers'); +var pathMatch = helpers.pathMatch; + +function webpackHotMiddleware(compiler, opts) { + opts = opts || {}; + opts.log = typeof opts.log == 'undefined' ? console.log.bind(console) : opts.log; + opts.path = opts.path || '/__webpack_hmr'; + opts.heartbeat = opts.heartbeat || 10 * 1000; + + var eventStream = createEventStream(opts.heartbeat); + var latestStats = null; + + if(compiler.hooks) { + compiler.hooks.run.tap("webpackHotMiddleware", function() { + latestStats = null; + if (opts.log) opts.log("webpack building..."); + eventStream.publish({action: "building"}); + }); + compiler.hooks.done.tap("webpackHotMiddleware", function(statsResult) { + // Keep hold of latest stats so they can be propagated to new clients + latestStats = statsResult; + publishStats("built", latestStats, eventStream, opts.log); + }); + } else { + compiler.plugin("compile", function() { + latestStats = null; + if (opts.log) opts.log("webpack building..."); + eventStream.publish({action: "building"}); + }); + compiler.plugin("done", function(statsResult) { + // Keep hold of latest stats so they can be propagated to new clients + latestStats = statsResult; + publishStats("built", latestStats, eventStream, opts.log); + }); + } + var middleware = function(req, res, next) { + if (!pathMatch(req.url, opts.path)) return next(); + eventStream.handler(req, res); + if (latestStats) { + // Explicitly not passing in `log` fn as we don't want to log again on + // the server + publishStats("sync", latestStats, eventStream); + } + }; + middleware.publish = eventStream.publish; + return middleware; +} + +function createEventStream(heartbeat) { + var clientId = 0; + var clients = {}; + function everyClient(fn) { + Object.keys(clients).forEach(function(id) { + fn(clients[id]); + }); + } + setInterval(function heartbeatTick() { + everyClient(function(client) { + client.write("data: \uD83D\uDC93\n\n"); + }); + }, heartbeat).unref(); + return { + handler: function(req, res) { + req.socket.setKeepAlive(true); + res.writeHead(200, { + 'Access-Control-Allow-Origin': '*', + 'Content-Type': 'text/event-stream;charset=utf-8', + 'Cache-Control': 'no-cache, no-transform', + 'Connection': 'keep-alive', + // While behind nginx, event stream should not be buffered: + // http://nginx.org/docs/http/ngx_http_proxy_module.html#proxy_buffering + 'X-Accel-Buffering': 'no' + }); + res.write('\n'); + var id = clientId++; + clients[id] = res; + req.on("close", function(){ + delete clients[id]; + }); + }, + publish: function(payload) { + everyClient(function(client) { + client.write("data: " + JSON.stringify(payload) + "\n\n"); + }); + } + }; +} + +function publishStats(action, statsResult, eventStream, log) { + // For multi-compiler, stats will be an object with a 'children' array of stats + var bundles = extractBundles(statsResult.toJson({ errorDetails: false })); + bundles.forEach(function(stats) { + if (log) { + log("webpack built " + (stats.name ? stats.name + " " : "") + + stats.hash + " in " + stats.time + "ms"); + } + eventStream.publish({ + name: stats.name, + action: action, + time: stats.time, + hash: stats.hash, + warnings: stats.warnings || [], + errors: stats.errors || [], + modules: buildModuleMap(stats.modules) + }); + }); +} + +function extractBundles(stats) { + // Stats has modules, single bundle + if (stats.modules) return [stats]; + + // Stats has children, multiple bundles + if (stats.children && stats.children.length) return stats.children; + + // Not sure, assume single + return [stats]; +} + +function buildModuleMap(modules) { + var map = {}; + modules.forEach(function(module) { + map[module.id] = module.name; + }); + return map; +} diff --git a/webpack.config.js b/webpack.config.js index 32263ce9..fc12fe06 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -24,6 +24,9 @@ module.exports = { store: 'app/web/store', vue: 'vue/dist/vue.js' }, + resolveLoader: { + modules: [ path.join(__dirname, 'node_modules/easywebpack-vue/node_modules') ] + }, dll: ['vue', 'axios', 'vue-router', 'vuex', 'vuex-router-sync'], loaders: {}, plugins: {},