Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 978f8b6

Browse filesBrowse files
committed
docs: include ssr setup in example
1 parent b85244b commit 978f8b6
Copy full SHA for 978f8b6

File tree

5 files changed

+164
-94
lines changed
Filter options

5 files changed

+164
-94
lines changed

‎.gitignore

Copy file name to clipboardExpand all lines: .gitignore
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
.DS_Store
33
node_modules
44
dist
5+
dist-ssr
56
link.sh
67
.cache
78
TODOs.md

‎example/main.js

Copy file name to clipboard
+7-2Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11
import App from './App.vue'
2-
import { createApp } from 'vue'
2+
import { createApp, createSSRApp } from 'vue'
33

4-
createApp(App).mount('#app')
4+
const app = __IS_SSR__ ? createSSRApp(App) : createApp(App)
5+
export default app
6+
7+
if (typeof window !== 'undefined') {
8+
app.mount('#app')
9+
}

‎example/ssr.js

Copy file name to clipboard
+20Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// This script is part of `yarn build-example-ssr`.
2+
3+
const fs = require('fs')
4+
const path = require('path')
5+
const { renderToString } = require('@vue/server-renderer')
6+
const template = fs.readFileSync(path.resolve(__dirname, 'index.html'), 'utf-8')
7+
8+
// here out server-side build directly exports an app instance.
9+
// in an actual SSR setup, you'll want to export a `createApp()` function that
10+
// returns a fresh app instance for each request. You probably also want to
11+
// return the router instance so that you can set the app's route state before
12+
// actually rendering it.
13+
const app = require('./dist-ssr/server/main.js').default
14+
15+
renderToString(app).then((html) => {
16+
fs.writeFileSync(
17+
path.resolve(__dirname, 'dist-ssr/index.html'),
18+
template.replace(/(<div id="app">)/, `$1${html}`)
19+
)
20+
})

‎example/webpack.config.js

Copy file name to clipboardExpand all lines: example/webpack.config.js
+135-92Lines changed: 135 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -7,104 +7,147 @@ const MiniCssExtractPlugin = require('mini-css-extract-plugin')
77

88
module.exports = (env = {}) => {
99
const isProd = env.prod
10-
const minimize = isProd && !env.noMinimize
11-
const babel = isProd && !env.noBabel
10+
const isSSR = env.ssr
1211

13-
return {
14-
mode: isProd ? 'production' : 'development',
15-
entry: path.resolve(__dirname, './main.js'),
16-
devtool: 'source-map',
17-
output: {
18-
path: path.resolve(__dirname, 'dist'),
19-
filename: '[name].js',
20-
publicPath: '/dist/',
21-
},
22-
module: {
23-
rules: [
24-
{
25-
test: /\.vue$/,
26-
loader: 'vue-loader',
27-
},
28-
{
29-
test: /\.png$/,
30-
use: [
31-
{
32-
loader: 'url-loader',
33-
options: {
34-
limit: 8192,
35-
},
12+
/**
13+
* Some notes regarding config for the server build of an SSR app:
14+
* 1. target: 'node'
15+
* 2. output.libraryTarget: 'commonjs' (so the exported app can be required)
16+
* 3. externals: this is mostly for faster builds.
17+
* - externalize @vue/* deps via commonjs require()
18+
* - externalize client side deps that are never used on the server, e.g.
19+
* ones that are only used in onMounted() to empty modules
20+
* 4. If using cache-loader or any other forms of cache, make sure the cache
21+
* key takes client vs. server builds into account!
22+
*/
23+
const genConfig = (isServerBuild = false) => {
24+
const minimize = isProd && !isServerBuild && !env.noMinimize
25+
const useBabel = isProd && !isServerBuild && !env.noBabel
26+
27+
return {
28+
mode: isProd ? 'production' : 'development',
29+
entry: path.resolve(__dirname, './main.js'),
30+
target: isServerBuild ? 'node' : 'web',
31+
devtool: 'source-map',
32+
output: {
33+
path: path.resolve(
34+
__dirname,
35+
isSSR ? (isServerBuild ? 'dist-ssr/server' : 'dist-ssr/dist') : 'dist'
36+
),
37+
filename: '[name].js',
38+
publicPath: '/dist/',
39+
libraryTarget: isServerBuild ? 'commonjs' : undefined,
40+
},
41+
externals: isServerBuild
42+
? [
43+
(ctx, request, cb) => {
44+
if (/^@vue/.test(request)) {
45+
return cb(null, 'commonjs ' + request)
46+
}
47+
cb()
3648
},
37-
],
38-
},
39-
{
40-
test: /\.css$/,
41-
use: [
42-
{
43-
loader: MiniCssExtractPlugin.loader,
44-
options: {
45-
hmr: !isProd,
49+
]
50+
: undefined,
51+
module: {
52+
rules: [
53+
{
54+
test: /\.vue$/,
55+
loader: 'vue-loader',
56+
},
57+
{
58+
test: /\.png$/,
59+
use: [
60+
{
61+
loader: 'url-loader',
62+
options: {
63+
limit: 8192,
64+
},
4665
},
47-
},
48-
'css-loader',
49-
],
50-
},
51-
{
52-
test: /\.js$/,
53-
use: [
54-
{
55-
loader: 'cache-loader',
56-
options: {
57-
cacheIdentifier: hash(
58-
fs.readFileSync(path.resolve(__dirname, '../package.json')) +
59-
JSON.stringify(env)
60-
),
61-
cacheDirectory: path.resolve(__dirname, '../.cache'),
66+
],
67+
},
68+
{
69+
test: /\.css$/,
70+
use: [
71+
{
72+
loader: MiniCssExtractPlugin.loader,
73+
options: {
74+
hmr: !isProd,
75+
},
6276
},
63-
},
64-
...(babel
65-
? [
66-
{
67-
loader: 'babel-loader',
68-
options: {
69-
// use yarn build-example --env.noMinimize to verify that
70-
// babel is properly applied to all js code, including the
71-
// render function compiled from SFC templates.
72-
presets: ['@babel/preset-env'],
77+
'css-loader',
78+
],
79+
},
80+
{
81+
test: /\.js$/,
82+
use: [
83+
{
84+
loader: 'cache-loader',
85+
options: {
86+
cacheIdentifier: hash(
87+
// deps
88+
fs.readFileSync(
89+
path.resolve(__dirname, '../package.json')
90+
) +
91+
// env
92+
JSON.stringify(env) +
93+
// client vs. server build
94+
isServerBuild
95+
),
96+
cacheDirectory: path.resolve(__dirname, '../.cache'),
97+
},
98+
},
99+
...(useBabel
100+
? [
101+
{
102+
loader: 'babel-loader',
103+
options: {
104+
// use yarn build-example --env.noMinimize to verify that
105+
// babel is properly applied to all js code, including the
106+
// render function compiled from SFC templates.
107+
presets: ['@babel/preset-env'],
108+
},
73109
},
74-
},
75-
]
76-
: []),
77-
],
78-
},
79-
// target <docs> custom blocks
80-
{
81-
resourceQuery: /blockType=docs/,
82-
loader: require.resolve('./docs-loader'),
83-
},
110+
]
111+
: []),
112+
],
113+
},
114+
// target <docs> custom blocks
115+
{
116+
resourceQuery: /blockType=docs/,
117+
loader: require.resolve('./docs-loader'),
118+
},
119+
],
120+
},
121+
plugins: [
122+
new VueLoaderPlugin(),
123+
new MiniCssExtractPlugin({
124+
filename: '[name].css',
125+
}),
126+
new webpack.DefinePlugin({
127+
__IS_SSR__: !!isSSR,
128+
__VUE_OPTIONS_API__: true,
129+
__VUE_PROD_DEVTOOLS__: false,
130+
}),
84131
],
85-
},
86-
plugins: [
87-
new VueLoaderPlugin(),
88-
new MiniCssExtractPlugin({
89-
filename: '[name].css',
90-
}),
91-
new webpack.DefinePlugin({
92-
__VUE_OPTIONS_API__: true,
93-
__VUE_PROD_DEVTOOLS__: false,
94-
}),
95-
],
96-
optimization: {
97-
minimize,
98-
},
99-
devServer: {
100-
stats: 'minimal',
101-
contentBase: __dirname,
102-
overlay: true,
103-
},
104-
resolveLoader: {
105-
alias: {
106-
'vue-loader': require.resolve('../'),
132+
optimization: {
133+
minimize,
134+
},
135+
devServer: {
136+
stats: 'minimal',
137+
contentBase: __dirname,
138+
overlay: true,
107139
},
108-
},
140+
resolveLoader: {
141+
alias: {
142+
'vue-loader': require.resolve('../'),
143+
},
144+
},
145+
}
146+
}
147+
148+
if (!isSSR) {
149+
return genConfig()
150+
} else {
151+
return [genConfig(), genConfig(true)]
109152
}
110153
}

‎package.json

Copy file name to clipboardExpand all lines: package.json
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
"test:webpack5": "WEBPACK5=true jest -c --coverage",
1717
"dev-example": "webpack-dev-server --config example/webpack.config.js --inline --hot",
1818
"build-example": "rm -rf example/dist && webpack --config example/webpack.config.js --env.prod",
19+
"build-example-ssr": "rm -rf example/dist-ssr && webpack --config example/webpack.config.js --env.prod --env.ssr && node example/ssr.js",
1920
"lint": "prettier --write --parser typescript \"{src,test}/**/*.{j,t}s\"",
2021
"prepublishOnly": "tsc"
2122
},

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.