Skip to content

Commit a2bff57

Browse files
committed
include ssr webpack plugin in main repo
1 parent 745fcd6 commit a2bff57

File tree

7 files changed

+198
-31
lines changed

7 files changed

+198
-31
lines changed

build/config.js

Lines changed: 42 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
const path = require('path')
2-
const flow = require('rollup-plugin-flow-no-whitespace')
32
const buble = require('rollup-plugin-buble')
4-
const replace = require('rollup-plugin-replace')
53
const alias = require('rollup-plugin-alias')
4+
const replace = require('rollup-plugin-replace')
5+
const flow = require('rollup-plugin-flow-no-whitespace')
66
const version = process.env.VERSION || require('../package.json').version
77
const weexVersion = process.env.WEEX_VERSION || require('../packages/weex-vue-framework/package.json').version
88

@@ -22,106 +22,120 @@ const weexFactoryPlugin = {
2222
}
2323
}
2424

25+
const resolve = p => path.resolve(__dirname, '../' + p)
26+
2527
const builds = {
2628
// Runtime only (CommonJS). Used by bundlers e.g. Webpack & Browserify
2729
'web-runtime-cjs': {
28-
entry: path.resolve(__dirname, '../src/entries/web-runtime.js'),
29-
dest: path.resolve(__dirname, '../dist/vue.runtime.common.js'),
30+
entry: resolve('src/entries/web-runtime.js'),
31+
dest: resolve('dist/vue.runtime.common.js'),
3032
format: 'cjs',
3133
banner
3234
},
3335
// Runtime+compiler CommonJS build (CommonJS)
3436
'web-full-cjs': {
35-
entry: path.resolve(__dirname, '../src/entries/web-runtime-with-compiler.js'),
36-
dest: path.resolve(__dirname, '../dist/vue.common.js'),
37+
entry: resolve('src/entries/web-runtime-with-compiler.js'),
38+
dest: resolve('dist/vue.common.js'),
3739
format: 'cjs',
3840
alias: { he: './entity-decoder' },
3941
banner
4042
},
4143
// Runtime only (ES Modules). Used by bundlers that support ES Modules,
4244
// e.g. Rollup & Webpack 2
4345
'web-runtime-esm': {
44-
entry: path.resolve(__dirname, '../src/entries/web-runtime.js'),
45-
dest: path.resolve(__dirname, '../dist/vue.runtime.esm.js'),
46+
entry: resolve('src/entries/web-runtime.js'),
47+
dest: resolve('dist/vue.runtime.esm.js'),
4648
format: 'es',
4749
banner
4850
},
4951
// Runtime+compiler CommonJS build (ES Modules)
5052
'web-full-esm': {
51-
entry: path.resolve(__dirname, '../src/entries/web-runtime-with-compiler.js'),
52-
dest: path.resolve(__dirname, '../dist/vue.esm.js'),
53+
entry: resolve('src/entries/web-runtime-with-compiler.js'),
54+
dest: resolve('dist/vue.esm.js'),
5355
format: 'es',
5456
alias: { he: './entity-decoder' },
5557
banner
5658
},
5759
// runtime-only build (Browser)
5860
'web-runtime-dev': {
59-
entry: path.resolve(__dirname, '../src/entries/web-runtime.js'),
60-
dest: path.resolve(__dirname, '../dist/vue.runtime.js'),
61+
entry: resolve('src/entries/web-runtime.js'),
62+
dest: resolve('dist/vue.runtime.js'),
6163
format: 'umd',
6264
env: 'development',
6365
banner
6466
},
6567
// runtime-only production build (Browser)
6668
'web-runtime-prod': {
67-
entry: path.resolve(__dirname, '../src/entries/web-runtime.js'),
68-
dest: path.resolve(__dirname, '../dist/vue.runtime.min.js'),
69+
entry: resolve('src/entries/web-runtime.js'),
70+
dest: resolve('dist/vue.runtime.min.js'),
6971
format: 'umd',
7072
env: 'production',
7173
banner
7274
},
7375
// Runtime+compiler development build (Browser)
7476
'web-full-dev': {
75-
entry: path.resolve(__dirname, '../src/entries/web-runtime-with-compiler.js'),
76-
dest: path.resolve(__dirname, '../dist/vue.js'),
77+
entry: resolve('src/entries/web-runtime-with-compiler.js'),
78+
dest: resolve('dist/vue.js'),
7779
format: 'umd',
7880
env: 'development',
7981
alias: { he: './entity-decoder' },
8082
banner
8183
},
8284
// Runtime+compiler production build (Browser)
8385
'web-full-prod': {
84-
entry: path.resolve(__dirname, '../src/entries/web-runtime-with-compiler.js'),
85-
dest: path.resolve(__dirname, '../dist/vue.min.js'),
86+
entry: resolve('src/entries/web-runtime-with-compiler.js'),
87+
dest: resolve('dist/vue.min.js'),
8688
format: 'umd',
8789
env: 'production',
8890
alias: { he: './entity-decoder' },
8991
banner
9092
},
9193
// Web compiler (CommonJS).
9294
'web-compiler': {
93-
entry: path.resolve(__dirname, '../src/entries/web-compiler.js'),
94-
dest: path.resolve(__dirname, '../packages/vue-template-compiler/build.js'),
95+
entry: resolve('src/entries/web-compiler.js'),
96+
dest: resolve('packages/vue-template-compiler/build.js'),
9597
format: 'cjs',
9698
external: Object.keys(require('../packages/vue-template-compiler/package.json').dependencies)
9799
},
98100
// Web server renderer (CommonJS).
99101
'web-server-renderer': {
100-
entry: path.resolve(__dirname, '../src/entries/web-server-renderer.js'),
101-
dest: path.resolve(__dirname, '../packages/vue-server-renderer/build.js'),
102+
entry: resolve('src/entries/web-server-renderer.js'),
103+
dest: resolve('packages/vue-server-renderer/build.js'),
104+
format: 'cjs',
105+
external: Object.keys(require('../packages/vue-server-renderer/package.json').dependencies)
106+
},
107+
'web-server-renderer-webpack-server-plugin': {
108+
entry: resolve('src/server/webpack-plugin/server.js'),
109+
dest: resolve('packages/vue-server-renderer/server-plugin.js'),
110+
format: 'cjs',
111+
external: Object.keys(require('../packages/vue-server-renderer/package.json').dependencies)
112+
},
113+
'web-server-renderer-webpack-client-plugin': {
114+
entry: resolve('src/server/webpack-plugin/client.js'),
115+
dest: resolve('packages/vue-server-renderer/client-plugin.js'),
102116
format: 'cjs',
103117
external: Object.keys(require('../packages/vue-server-renderer/package.json').dependencies)
104118
},
105119
// Weex runtime factory
106120
'weex-factory': {
107121
weex: true,
108-
entry: path.resolve(__dirname, '../src/entries/weex-factory.js'),
109-
dest: path.resolve(__dirname, '../packages/weex-vue-framework/factory.js'),
122+
entry: resolve('src/entries/weex-factory.js'),
123+
dest: resolve('packages/weex-vue-framework/factory.js'),
110124
format: 'cjs',
111125
plugins: [weexFactoryPlugin]
112126
},
113127
// Weex runtime framework (CommonJS).
114128
'weex-framework': {
115129
weex: true,
116-
entry: path.resolve(__dirname, '../src/entries/weex-framework.js'),
117-
dest: path.resolve(__dirname, '../packages/weex-vue-framework/index.js'),
130+
entry: resolve('src/entries/weex-framework.js'),
131+
dest: resolve('packages/weex-vue-framework/index.js'),
118132
format: 'cjs'
119133
},
120134
// Weex compiler (CommonJS). Used by Weex's Webpack loader.
121135
'weex-compiler': {
122136
weex: true,
123-
entry: path.resolve(__dirname, '../src/entries/weex-compiler.js'),
124-
dest: path.resolve(__dirname, '../packages/weex-template-compiler/build.js'),
137+
entry: resolve('src/entries/weex-compiler.js'),
138+
dest: resolve('packages/weex-template-compiler/build.js'),
125139
format: 'cjs',
126140
external: Object.keys(require('../packages/weex-template-compiler/package.json').dependencies)
127141
}

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
"babel-preset-es2015": "^6.9.0",
6565
"babel-preset-flow-vue": "^1.0.0",
6666
"buble": "^0.15.2",
67+
"chalk": "^1.1.3",
6768
"chromedriver": "^2.21.2",
6869
"codecov.io": "^0.1.6",
6970
"cross-spawn": "^5.0.1",

packages/vue-server-renderer/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
"url": "https://github.com/vuejs/vue/issues"
1919
},
2020
"dependencies": {
21+
"chalk": "^1.1.3",
22+
"hash-sum": "^1.0.2",
2123
"he": "^1.1.0",
2224
"de-indent": "^1.0.2",
2325
"resolve": "^1.2.0",

src/server/webpack-plugin/client.js

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
const hash = require('hash-sum')
2+
import { isJS } from './util'
3+
4+
export default class VueSSRClientPlugin {
5+
constructor (options = {}) {
6+
this.options = Object.assign({
7+
filename: 'vue-ssr-client-manifest.json'
8+
}, options)
9+
}
10+
11+
apply (compiler) {
12+
compiler.plugin('emit', (compilation, cb) => {
13+
const stats = compilation.getStats().toJson()
14+
15+
const allFiles = stats.assets
16+
.map(a => a.name)
17+
18+
const initialScripts = Object.keys(stats.entrypoints)
19+
.map(name => stats.entrypoints[name].assets)
20+
.reduce((assets, all) => all.concat(assets), [])
21+
.filter(isJS)
22+
23+
const asyncScripts = allFiles
24+
.filter(isJS)
25+
.filter(file => initialScripts.indexOf(file) < 0)
26+
27+
const manifest = {
28+
publicPath: stats.publicPath,
29+
all: allFiles,
30+
initial: initialScripts,
31+
async: asyncScripts,
32+
modules: { /* [identifier: string]: Array<index: number> */ }
33+
}
34+
35+
const assetModules = stats.modules.filter(m => m.assets.length)
36+
const fileToIndex = file => manifest.all.indexOf(file)
37+
stats.modules.forEach(m => {
38+
// ignore modules duplicated in multiple chunks
39+
if (m.chunks.length === 1) {
40+
const cid = m.chunks[0]
41+
const chunk = stats.chunks.find(c => c.id === cid)
42+
const files = manifest.modules[hash(m.identifier)] = chunk.files.map(fileToIndex)
43+
// find all asset modules associated with the same chunk
44+
assetModules.forEach(m => {
45+
if (m.chunks.some(id => id === cid)) {
46+
files.push.apply(files, m.assets.map(fileToIndex))
47+
}
48+
})
49+
}
50+
})
51+
52+
// const debug = (file, obj) => {
53+
// require('fs').writeFileSync(__dirname + '/' + file, JSON.stringify(obj, null, 2))
54+
// }
55+
// debug('stats.json', stats)
56+
// debug('client-manifest.json', manifest)
57+
58+
const json = JSON.stringify(manifest, null, 2)
59+
compilation.assets[this.options.filename] = {
60+
source: () => json,
61+
size: () => json.length
62+
}
63+
cb()
64+
})
65+
}
66+
}

src/server/webpack-plugin/server.js

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { validate, isJS } from './util'
2+
3+
export default class VueSSRServerPlugin {
4+
constructor (options = {}) {
5+
this.options = Object.assign({
6+
filename: 'vue-ssr-server-bundle.json'
7+
}, options)
8+
}
9+
10+
apply (compiler) {
11+
validate(compiler)
12+
13+
compiler.plugin('emit', (compilation, cb) => {
14+
const stats = compilation.getStats().toJson()
15+
const entryName = Object.keys(stats.entrypoints)[0]
16+
const entryAssets = stats.entrypoints[entryName].assets.filter(isJS)
17+
18+
if (entryAssets.length > 1) {
19+
throw new Error(
20+
`Server-side bundle should have one single entry file. ` +
21+
`Avoid using CommonsChunkPlugin in the server config.`
22+
)
23+
}
24+
25+
const entry = entryAssets[0]
26+
if (!entry || typeof entry !== 'string') {
27+
throw new Error(
28+
`Entry "${entryName}" not found. Did you specify the correct entry option?`
29+
)
30+
}
31+
32+
const bundle = {
33+
entry,
34+
files: {},
35+
maps: {}
36+
}
37+
38+
stats.assets.forEach(asset => {
39+
if (asset.name.match(/\.js$/)) {
40+
bundle.files[asset.name] = compilation.assets[asset.name].source()
41+
} else if (asset.name.match(/\.map$/)) {
42+
bundle.maps[asset.name.replace(/\.map$/, '')] = JSON.parse(compilation.assets[asset.name].source())
43+
}
44+
// do not emit anything else for server
45+
delete compilation.assets[asset.name]
46+
})
47+
48+
const json = JSON.stringify(bundle, null, 2)
49+
const filename = this.options.filename
50+
51+
compilation.assets[filename] = {
52+
source: () => json,
53+
size: () => json.length
54+
}
55+
56+
cb()
57+
})
58+
}
59+
}

src/server/webpack-plugin/util.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
const { red, yellow, gray } = require('chalk')
2+
3+
const prefix = `[vue-server-renderer-webpack-plugin]`
4+
const warn = exports.warn = msg => console.error(red(`${prefix} ${msg}\n`))
5+
const tip = exports.tip = msg => console.log(yellow(`${prefix} ${msg}\n`))
6+
7+
export const validate = compiler => {
8+
if (compiler.options.target !== 'node') {
9+
warn('webpack config `target` should be "node".')
10+
}
11+
12+
if (compiler.options.output && compiler.options.output.libraryTarget !== 'commonjs2') {
13+
warn('webpack config `output.libraryTarget` should be "commonjs2".')
14+
}
15+
16+
if (!compiler.options.externals) {
17+
tip(
18+
'It is recommended to externalize dependencies for better ssr performance.\n' +
19+
`See ${gray('https://github.com/vuejs/vue/tree/dev/packages/vue-server-renderer#externals')} ` +
20+
'for more details.'
21+
)
22+
}
23+
}
24+
25+
export const isJS = file => /\.js($|\?)/.test(file)

yarn.lock

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5058,9 +5058,9 @@ void-elements@^2.0.0:
50585058
version "2.0.1"
50595059
resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec"
50605060

5061-
vue-ssr-webpack-plugin@^2.0.0:
5062-
version "2.0.2"
5063-
resolved "https://registry.yarnpkg.com/vue-ssr-webpack-plugin/-/vue-ssr-webpack-plugin-2.0.2.tgz#80709e7d53e1fe7085ad3dc73afff71c069be715"
5061+
vue-ssr-webpack-plugin@^3.0.0:
5062+
version "3.0.0"
5063+
resolved "https://registry.yarnpkg.com/vue-ssr-webpack-plugin/-/vue-ssr-webpack-plugin-3.0.0.tgz#db47769ed8e71c8eb53aa9ae7be9ff04baf546fa"
50645064
dependencies:
50655065
chalk "^1.1.3"
50665066
hash-sum "^1.0.2"

0 commit comments

Comments
 (0)