Browse Source

include ssr webpack plugin in main repo

dev
Evan You 8 years ago
parent
commit
a2bff57b0d
  1. 70
      build/config.js
  2. 1
      package.json
  3. 2
      packages/vue-server-renderer/package.json
  4. 66
      src/server/webpack-plugin/client.js
  5. 59
      src/server/webpack-plugin/server.js
  6. 25
      src/server/webpack-plugin/util.js
  7. 6
      yarn.lock

70
build/config.js

@ -1,8 +1,8 @@
const path = require('path') const path = require('path')
const flow = require('rollup-plugin-flow-no-whitespace')
const buble = require('rollup-plugin-buble') const buble = require('rollup-plugin-buble')
const replace = require('rollup-plugin-replace')
const alias = require('rollup-plugin-alias') const alias = require('rollup-plugin-alias')
const replace = require('rollup-plugin-replace')
const flow = require('rollup-plugin-flow-no-whitespace')
const version = process.env.VERSION || require('../package.json').version const version = process.env.VERSION || require('../package.json').version
const weexVersion = process.env.WEEX_VERSION || require('../packages/weex-vue-framework/package.json').version const weexVersion = process.env.WEEX_VERSION || require('../packages/weex-vue-framework/package.json').version
@ -22,18 +22,20 @@ const weexFactoryPlugin = {
} }
} }
const resolve = p => path.resolve(__dirname, '../' + p)
const builds = { const builds = {
// Runtime only (CommonJS). Used by bundlers e.g. Webpack & Browserify // Runtime only (CommonJS). Used by bundlers e.g. Webpack & Browserify
'web-runtime-cjs': { 'web-runtime-cjs': {
entry: path.resolve(__dirname, '../src/entries/web-runtime.js'), entry: resolve('src/entries/web-runtime.js'),
dest: path.resolve(__dirname, '../dist/vue.runtime.common.js'), dest: resolve('dist/vue.runtime.common.js'),
format: 'cjs', format: 'cjs',
banner banner
}, },
// Runtime+compiler CommonJS build (CommonJS) // Runtime+compiler CommonJS build (CommonJS)
'web-full-cjs': { 'web-full-cjs': {
entry: path.resolve(__dirname, '../src/entries/web-runtime-with-compiler.js'), entry: resolve('src/entries/web-runtime-with-compiler.js'),
dest: path.resolve(__dirname, '../dist/vue.common.js'), dest: resolve('dist/vue.common.js'),
format: 'cjs', format: 'cjs',
alias: { he: './entity-decoder' }, alias: { he: './entity-decoder' },
banner banner
@ -41,39 +43,39 @@ const builds = {
// Runtime only (ES Modules). Used by bundlers that support ES Modules, // Runtime only (ES Modules). Used by bundlers that support ES Modules,
// e.g. Rollup & Webpack 2 // e.g. Rollup & Webpack 2
'web-runtime-esm': { 'web-runtime-esm': {
entry: path.resolve(__dirname, '../src/entries/web-runtime.js'), entry: resolve('src/entries/web-runtime.js'),
dest: path.resolve(__dirname, '../dist/vue.runtime.esm.js'), dest: resolve('dist/vue.runtime.esm.js'),
format: 'es', format: 'es',
banner banner
}, },
// Runtime+compiler CommonJS build (ES Modules) // Runtime+compiler CommonJS build (ES Modules)
'web-full-esm': { 'web-full-esm': {
entry: path.resolve(__dirname, '../src/entries/web-runtime-with-compiler.js'), entry: resolve('src/entries/web-runtime-with-compiler.js'),
dest: path.resolve(__dirname, '../dist/vue.esm.js'), dest: resolve('dist/vue.esm.js'),
format: 'es', format: 'es',
alias: { he: './entity-decoder' }, alias: { he: './entity-decoder' },
banner banner
}, },
// runtime-only build (Browser) // runtime-only build (Browser)
'web-runtime-dev': { 'web-runtime-dev': {
entry: path.resolve(__dirname, '../src/entries/web-runtime.js'), entry: resolve('src/entries/web-runtime.js'),
dest: path.resolve(__dirname, '../dist/vue.runtime.js'), dest: resolve('dist/vue.runtime.js'),
format: 'umd', format: 'umd',
env: 'development', env: 'development',
banner banner
}, },
// runtime-only production build (Browser) // runtime-only production build (Browser)
'web-runtime-prod': { 'web-runtime-prod': {
entry: path.resolve(__dirname, '../src/entries/web-runtime.js'), entry: resolve('src/entries/web-runtime.js'),
dest: path.resolve(__dirname, '../dist/vue.runtime.min.js'), dest: resolve('dist/vue.runtime.min.js'),
format: 'umd', format: 'umd',
env: 'production', env: 'production',
banner banner
}, },
// Runtime+compiler development build (Browser) // Runtime+compiler development build (Browser)
'web-full-dev': { 'web-full-dev': {
entry: path.resolve(__dirname, '../src/entries/web-runtime-with-compiler.js'), entry: resolve('src/entries/web-runtime-with-compiler.js'),
dest: path.resolve(__dirname, '../dist/vue.js'), dest: resolve('dist/vue.js'),
format: 'umd', format: 'umd',
env: 'development', env: 'development',
alias: { he: './entity-decoder' }, alias: { he: './entity-decoder' },
@ -81,8 +83,8 @@ const builds = {
}, },
// Runtime+compiler production build (Browser) // Runtime+compiler production build (Browser)
'web-full-prod': { 'web-full-prod': {
entry: path.resolve(__dirname, '../src/entries/web-runtime-with-compiler.js'), entry: resolve('src/entries/web-runtime-with-compiler.js'),
dest: path.resolve(__dirname, '../dist/vue.min.js'), dest: resolve('dist/vue.min.js'),
format: 'umd', format: 'umd',
env: 'production', env: 'production',
alias: { he: './entity-decoder' }, alias: { he: './entity-decoder' },
@ -90,38 +92,50 @@ const builds = {
}, },
// Web compiler (CommonJS). // Web compiler (CommonJS).
'web-compiler': { 'web-compiler': {
entry: path.resolve(__dirname, '../src/entries/web-compiler.js'), entry: resolve('src/entries/web-compiler.js'),
dest: path.resolve(__dirname, '../packages/vue-template-compiler/build.js'), dest: resolve('packages/vue-template-compiler/build.js'),
format: 'cjs', format: 'cjs',
external: Object.keys(require('../packages/vue-template-compiler/package.json').dependencies) external: Object.keys(require('../packages/vue-template-compiler/package.json').dependencies)
}, },
// Web server renderer (CommonJS). // Web server renderer (CommonJS).
'web-server-renderer': { 'web-server-renderer': {
entry: path.resolve(__dirname, '../src/entries/web-server-renderer.js'), entry: resolve('src/entries/web-server-renderer.js'),
dest: path.resolve(__dirname, '../packages/vue-server-renderer/build.js'), dest: resolve('packages/vue-server-renderer/build.js'),
format: 'cjs',
external: Object.keys(require('../packages/vue-server-renderer/package.json').dependencies)
},
'web-server-renderer-webpack-server-plugin': {
entry: resolve('src/server/webpack-plugin/server.js'),
dest: resolve('packages/vue-server-renderer/server-plugin.js'),
format: 'cjs',
external: Object.keys(require('../packages/vue-server-renderer/package.json').dependencies)
},
'web-server-renderer-webpack-client-plugin': {
entry: resolve('src/server/webpack-plugin/client.js'),
dest: resolve('packages/vue-server-renderer/client-plugin.js'),
format: 'cjs', format: 'cjs',
external: Object.keys(require('../packages/vue-server-renderer/package.json').dependencies) external: Object.keys(require('../packages/vue-server-renderer/package.json').dependencies)
}, },
// Weex runtime factory // Weex runtime factory
'weex-factory': { 'weex-factory': {
weex: true, weex: true,
entry: path.resolve(__dirname, '../src/entries/weex-factory.js'), entry: resolve('src/entries/weex-factory.js'),
dest: path.resolve(__dirname, '../packages/weex-vue-framework/factory.js'), dest: resolve('packages/weex-vue-framework/factory.js'),
format: 'cjs', format: 'cjs',
plugins: [weexFactoryPlugin] plugins: [weexFactoryPlugin]
}, },
// Weex runtime framework (CommonJS). // Weex runtime framework (CommonJS).
'weex-framework': { 'weex-framework': {
weex: true, weex: true,
entry: path.resolve(__dirname, '../src/entries/weex-framework.js'), entry: resolve('src/entries/weex-framework.js'),
dest: path.resolve(__dirname, '../packages/weex-vue-framework/index.js'), dest: resolve('packages/weex-vue-framework/index.js'),
format: 'cjs' format: 'cjs'
}, },
// Weex compiler (CommonJS). Used by Weex's Webpack loader. // Weex compiler (CommonJS). Used by Weex's Webpack loader.
'weex-compiler': { 'weex-compiler': {
weex: true, weex: true,
entry: path.resolve(__dirname, '../src/entries/weex-compiler.js'), entry: resolve('src/entries/weex-compiler.js'),
dest: path.resolve(__dirname, '../packages/weex-template-compiler/build.js'), dest: resolve('packages/weex-template-compiler/build.js'),
format: 'cjs', format: 'cjs',
external: Object.keys(require('../packages/weex-template-compiler/package.json').dependencies) external: Object.keys(require('../packages/weex-template-compiler/package.json').dependencies)
} }

1
package.json

@ -64,6 +64,7 @@
"babel-preset-es2015": "^6.9.0", "babel-preset-es2015": "^6.9.0",
"babel-preset-flow-vue": "^1.0.0", "babel-preset-flow-vue": "^1.0.0",
"buble": "^0.15.2", "buble": "^0.15.2",
"chalk": "^1.1.3",
"chromedriver": "^2.21.2", "chromedriver": "^2.21.2",
"codecov.io": "^0.1.6", "codecov.io": "^0.1.6",
"cross-spawn": "^5.0.1", "cross-spawn": "^5.0.1",

2
packages/vue-server-renderer/package.json

@ -18,6 +18,8 @@
"url": "https://github.com/vuejs/vue/issues" "url": "https://github.com/vuejs/vue/issues"
}, },
"dependencies": { "dependencies": {
"chalk": "^1.1.3",
"hash-sum": "^1.0.2",
"he": "^1.1.0", "he": "^1.1.0",
"de-indent": "^1.0.2", "de-indent": "^1.0.2",
"resolve": "^1.2.0", "resolve": "^1.2.0",

66
src/server/webpack-plugin/client.js

@ -0,0 +1,66 @@
const hash = require('hash-sum')
import { isJS } from './util'
export default class VueSSRClientPlugin {
constructor (options = {}) {
this.options = Object.assign({
filename: 'vue-ssr-client-manifest.json'
}, options)
}
apply (compiler) {
compiler.plugin('emit', (compilation, cb) => {
const stats = compilation.getStats().toJson()
const allFiles = stats.assets
.map(a => a.name)
const initialScripts = Object.keys(stats.entrypoints)
.map(name => stats.entrypoints[name].assets)
.reduce((assets, all) => all.concat(assets), [])
.filter(isJS)
const asyncScripts = allFiles
.filter(isJS)
.filter(file => initialScripts.indexOf(file) < 0)
const manifest = {
publicPath: stats.publicPath,
all: allFiles,
initial: initialScripts,
async: asyncScripts,
modules: { /* [identifier: string]: Array<index: number> */ }
}
const assetModules = stats.modules.filter(m => m.assets.length)
const fileToIndex = file => manifest.all.indexOf(file)
stats.modules.forEach(m => {
// ignore modules duplicated in multiple chunks
if (m.chunks.length === 1) {
const cid = m.chunks[0]
const chunk = stats.chunks.find(c => c.id === cid)
const files = manifest.modules[hash(m.identifier)] = chunk.files.map(fileToIndex)
// find all asset modules associated with the same chunk
assetModules.forEach(m => {
if (m.chunks.some(id => id === cid)) {
files.push.apply(files, m.assets.map(fileToIndex))
}
})
}
})
// const debug = (file, obj) => {
// require('fs').writeFileSync(__dirname + '/' + file, JSON.stringify(obj, null, 2))
// }
// debug('stats.json', stats)
// debug('client-manifest.json', manifest)
const json = JSON.stringify(manifest, null, 2)
compilation.assets[this.options.filename] = {
source: () => json,
size: () => json.length
}
cb()
})
}
}

59
src/server/webpack-plugin/server.js

@ -0,0 +1,59 @@
import { validate, isJS } from './util'
export default class VueSSRServerPlugin {
constructor (options = {}) {
this.options = Object.assign({
filename: 'vue-ssr-server-bundle.json'
}, options)
}
apply (compiler) {
validate(compiler)
compiler.plugin('emit', (compilation, cb) => {
const stats = compilation.getStats().toJson()
const entryName = Object.keys(stats.entrypoints)[0]
const entryAssets = stats.entrypoints[entryName].assets.filter(isJS)
if (entryAssets.length > 1) {
throw new Error(
`Server-side bundle should have one single entry file. ` +
`Avoid using CommonsChunkPlugin in the server config.`
)
}
const entry = entryAssets[0]
if (!entry || typeof entry !== 'string') {
throw new Error(
`Entry "${entryName}" not found. Did you specify the correct entry option?`
)
}
const bundle = {
entry,
files: {},
maps: {}
}
stats.assets.forEach(asset => {
if (asset.name.match(/\.js$/)) {
bundle.files[asset.name] = compilation.assets[asset.name].source()
} else if (asset.name.match(/\.map$/)) {
bundle.maps[asset.name.replace(/\.map$/, '')] = JSON.parse(compilation.assets[asset.name].source())
}
// do not emit anything else for server
delete compilation.assets[asset.name]
})
const json = JSON.stringify(bundle, null, 2)
const filename = this.options.filename
compilation.assets[filename] = {
source: () => json,
size: () => json.length
}
cb()
})
}
}

25
src/server/webpack-plugin/util.js

@ -0,0 +1,25 @@
const { red, yellow, gray } = require('chalk')
const prefix = `[vue-server-renderer-webpack-plugin]`
const warn = exports.warn = msg => console.error(red(`${prefix} ${msg}\n`))
const tip = exports.tip = msg => console.log(yellow(`${prefix} ${msg}\n`))
export const validate = compiler => {
if (compiler.options.target !== 'node') {
warn('webpack config `target` should be "node".')
}
if (compiler.options.output && compiler.options.output.libraryTarget !== 'commonjs2') {
warn('webpack config `output.libraryTarget` should be "commonjs2".')
}
if (!compiler.options.externals) {
tip(
'It is recommended to externalize dependencies for better ssr performance.\n' +
`See ${gray('https://github.com/vuejs/vue/tree/dev/packages/vue-server-renderer#externals')} ` +
'for more details.'
)
}
}
export const isJS = file => /\.js($|\?)/.test(file)

6
yarn.lock

@ -5058,9 +5058,9 @@ void-elements@^2.0.0:
version "2.0.1" version "2.0.1"
resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec" resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec"
vue-ssr-webpack-plugin@^2.0.0: vue-ssr-webpack-plugin@^3.0.0:
version "2.0.2" version "3.0.0"
resolved "https://registry.yarnpkg.com/vue-ssr-webpack-plugin/-/vue-ssr-webpack-plugin-2.0.2.tgz#80709e7d53e1fe7085ad3dc73afff71c069be715" resolved "https://registry.yarnpkg.com/vue-ssr-webpack-plugin/-/vue-ssr-webpack-plugin-3.0.0.tgz#db47769ed8e71c8eb53aa9ae7be9ff04baf546fa"
dependencies: dependencies:
chalk "^1.1.3" chalk "^1.1.3"
hash-sum "^1.0.2" hash-sum "^1.0.2"

Loading…
Cancel
Save