UNPKG

4.37 kBJavaScriptView Raw
1const path = require('path');
2const webpack = require('webpack');
3const makeDir = require('make-dir');
4const openBrowser = require('open');
5
6const {getWebpackConfig} = require('./webpack');
7const {getConfig} = require('./default');
8
9function emitVueSSR(ctx) {
10 if (!ctx.emitter) return;
11 setImmediate(() => {
12 if (!ctx.serverCompiling && !ctx.clientCompiling) {
13 ctx.emitter.emit('vue-ssr', {
14 serverBundle: ctx.serverBundle,
15 clientManifest: ctx.clientManifest,
16 });
17 }
18 });
19}
20
21function emitVueSSRClientManifest(ctx, assets) {
22 if (!ctx.emitter) return;
23
24 const fileName = 'vue-ssr-client-manifest.json';
25 if (!assets[fileName]) return;
26
27 ctx.clientManifest = JSON.parse(assets[fileName].source());
28 ctx.emitter.emit(
29 'vue-ssr-client-manifest',
30 ctx.clientManifest,
31 );
32 emitVueSSR(ctx);
33}
34
35function emitVueSSRServerBundle(ctx, assets) {
36 if (!ctx.emitter) return;
37
38 const fileName = 'vue-ssr-server-bundle.json';
39 if (!assets[fileName]) return;
40
41 ctx.serverBundle = JSON.parse(assets[fileName].source());
42 ctx.emitter.emit(
43 'vue-ssr-server-bundle',
44 ctx.serverBundle,
45 );
46 emitVueSSR(ctx);
47}
48
49function initSSRCompiler(options = {}, ctx) {
50 const config = options.config || {};
51 const webpackConfig = options.webpackConfig || {};
52
53 const finalSSRConfig = getConfig(config, 'development');
54 finalSSRConfig.destPath = ctx.devServerSSRPath;
55 finalSSRConfig.publicUrl = '/';
56 finalSSRConfig.isSSR = true;
57 finalSSRConfig.isSSRDevServer = true;
58
59 const finalSSRWebpackConfig = getWebpackConfig({
60 env: 'development',
61 config: finalSSRConfig,
62 webpackConfig,
63 });
64
65 const ssrCompiler = webpack(finalSSRWebpackConfig);
66 ssrCompiler.watch({}, (err, stats) => {
67 if (err) {
68 console.error(err);
69 return;
70 }
71
72 if (stats.hasErrors()) {
73 // ignore
74 }
75 });
76
77 ssrCompiler.hooks.done.tap('beforeCompile', () => {
78 ctx.serverCompiling = true;
79 });
80
81 ssrCompiler.hooks.emit.tapAsync('sm-webpack-dev-server', (compilation, callback) => {
82 emitVueSSRServerBundle(ctx, compilation.assets);
83 ctx.serverCompiling = false;
84 compilation.assets = {};
85 callback();
86 });
87
88 return ssrCompiler;
89}
90
91function getDevServerSSRPath(config, originalDestPath) {
92 const compileSSR = config.hasSSR && config.devServer.buildSSR;
93 const devServerSSRPath = path.join(originalDestPath, 'dev_server');
94 if (compileSSR) {
95 // make directory to keep compiled ssr bundle and client manifest
96 makeDir(devServerSSRPath)
97 .then(() => {})
98 .catch(err => console.error(err));
99 }
100
101 return devServerSSRPath;
102}
103
104function getCompiler(options = {}) {
105 const config = options.config || {};
106 const webpackConfig = options.webpackConfig || {};
107 const emitter = options.emitter;
108
109 const finalConfig = getConfig(config, 'development');
110 const originalDestPath = finalConfig.destPath;
111 finalConfig.isDevServer = true;
112 finalConfig.hasHotClient = false;
113 finalConfig.destPath = '.';
114 finalConfig.publicUrl = '/';
115
116 const compileSSR = finalConfig.hasSSR && finalConfig.devServer.buildSSR;
117
118 // server bundle and client manifest for vue ssr
119 const ctx = {
120 emitter,
121 devServerSSRPath: getDevServerSSRPath(finalConfig, originalDestPath),
122 serverBundle: null,
123 clientManifest: null,
124 clientCompiling: false,
125 serverCompiling: false,
126 };
127
128 const finalWebpackConfig = getWebpackConfig({
129 env: 'development',
130 devServer: true,
131 config: finalConfig,
132 webpackConfig,
133 });
134
135 let isFirstCompile = true;
136 const compiler = webpack(finalWebpackConfig);
137
138 compiler.hooks.done.tap('beforeCompile', () => {
139 ctx.clientCompiling = true;
140 });
141
142 compiler.hooks.emit.tapAsync('sm-webpack-dev-server', (compilation, callback) => {
143 if (compileSSR) {
144 emitVueSSRClientManifest(ctx, compilation.assets);
145 }
146
147 ctx.clientCompiling = false;
148 callback();
149 });
150
151 const devServerOpts = finalConfig.devServer || {};
152 compiler.hooks.done.tap('sm-webpack-dev-server', (stats) => {
153 if (stats.hasErrors()) return;
154
155 if (isFirstCompile) {
156 isFirstCompile = false;
157 if (finalConfig.openBrowser) {
158 const host = devServerOpts.wwwHost || 'localhost';
159 const port = devServerOpts.port || 3001;
160 const protocol = devServerOpts.https ? 'https' : 'http';
161 openBrowser(`${protocol}://${host}:${port}`);
162 }
163 }
164 });
165
166 if (compileSSR) {
167 initSSRCompiler(options, ctx);
168 }
169
170 return {
171 compiler,
172 config: finalConfig,
173 webpackConfig: finalWebpackConfig,
174 };
175}
176
177module.exports = {
178 getCompiler,
179};