@@ -7,104 +7,147 @@ const MiniCssExtractPlugin = require('mini-css-extract-plugin')
77
88module . 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 : / \. v u e $ / ,
26- loader : 'vue-loader' ,
27- } ,
28- {
29- test : / \. p n g $ / ,
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 ( / ^ @ v u e / . test ( request ) ) {
45+ return cb ( null , 'commonjs ' + request )
46+ }
47+ cb ( )
3648 } ,
37- ] ,
38- } ,
39- {
40- test : / \. c s s $ / ,
41- use : [
42- {
43- loader : MiniCssExtractPlugin . loader ,
44- options : {
45- hmr : ! isProd ,
49+ ]
50+ : undefined ,
51+ module : {
52+ rules : [
53+ {
54+ test : / \. v u e $ / ,
55+ loader : 'vue-loader' ,
56+ } ,
57+ {
58+ test : / \. p n g $ / ,
59+ use : [
60+ {
61+ loader : 'url-loader' ,
62+ options : {
63+ limit : 8192 ,
64+ } ,
4665 } ,
47- } ,
48- 'css-loader' ,
49- ] ,
50- } ,
51- {
52- test : / \. j s $ / ,
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 : / \. c s s $ / ,
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 : / \. j s $ / ,
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 : / b l o c k T y p e = d o c s / ,
82- loader : require . resolve ( './docs-loader' ) ,
83- } ,
110+ ]
111+ : [ ] ) ,
112+ ] ,
113+ } ,
114+ // target <docs> custom blocks
115+ {
116+ resourceQuery : / b l o c k T y p e = d o c s / ,
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}
0 commit comments