UNPKG

3.85 kBJavaScriptView Raw
1const { superstruct } = require('superstruct')
2const getFileNames = require('./getFileNames')
3
4module.exports = (api, config) => {
5 api.logger.debug('Validating config', config)
6 const struct = superstruct()
7
8 const entry = struct.optional(
9 struct.union(['string', 'array', 'object']),
10 'index'
11 )
12
13 const output = struct(
14 {
15 dir: 'string',
16 sourceMap: 'boolean',
17 minimize: 'boolean',
18 format: struct.enum(['iife', 'cjs', 'umd']),
19 moduleName: struct.optional('string'),
20 publicUrl: 'string',
21 target: struct.enum(['browser', 'electron', 'node']),
22 clean: 'boolean',
23 fileNames: struct.optional(
24 struct.object({
25 js: struct.optional('string'),
26 css: struct.optional('string'),
27 font: struct.optional('string'),
28 image: struct.optional('string')
29 })
30 ),
31 html: struct.optional(struct.union(['boolean', 'object']))
32 },
33 {
34 dir: 'dist',
35 sourceMap: !api.isProd,
36 minimize: api.isProd,
37 format: 'iife',
38 publicUrl: '/',
39 target: 'browser',
40 default: true,
41 clean: true
42 }
43 )
44
45 const babel = struct(
46 {
47 jsx: 'string',
48 transpileModules: struct.optional(struct.list(['string'])),
49 namedImports: struct.optional('object')
50 },
51 {
52 jsx: 'react'
53 }
54 )
55
56 const css = struct(
57 {
58 extract: 'boolean',
59 loaderOptions: struct.optional(
60 struct.object({
61 css: struct.optional('object'),
62 less: struct.optional('object'),
63 postcss: struct.optional('object'),
64 sass: struct.optional('object'),
65 stylus: struct.optional('object')
66 })
67 )
68 },
69 {
70 extract: api.isProd
71 }
72 )
73
74 const devServer = struct(
75 {
76 hot: 'boolean',
77 hotOnly: 'boolean?',
78 host: 'string',
79 port: struct.union(['string', 'number']),
80 hotEntries: struct(['string']),
81 proxy: struct.optional(
82 struct.union([
83 'string',
84 'object',
85 'function',
86 struct([struct.union(['object', 'function'])])
87 ])
88 ),
89 open: 'boolean',
90 historyApiFallback: struct.optional(struct.union(['boolean', 'object'])),
91 before: struct.optional('function'),
92 after: struct.optional('function'),
93 https: struct.optional(struct.union(['boolean', 'object']))
94 },
95 {
96 hot: true,
97 host: '0.0.0.0',
98 port: 4000,
99 hotEntries: ['index'],
100 open: false
101 }
102 )
103
104 const plugins = struct.optional([
105 struct.union([
106 'string',
107 struct({
108 resolve: struct.union(['string', 'object']),
109 options: struct.optional('object')
110 })
111 ])
112 ])
113
114 const assets = struct(
115 {
116 inlineImageMaxSize: struct.optional('number')
117 },
118 {
119 inlineImageMaxSize: 5000
120 }
121 )
122
123 const Struct = struct(
124 {
125 entry,
126 output,
127 plugins,
128 parallel: 'boolean',
129 cache: 'boolean',
130 babel,
131 css,
132 devServer,
133 envs: struct.optional('object'),
134 constants: struct.optional('object'),
135 chainWebpack: struct.optional('function'),
136 configureWebpack: struct.optional(struct.union(['object', 'function'])),
137 assets,
138 publicFolder: struct.union(['string', 'boolean']),
139 pages: struct.optional('object')
140 },
141 {
142 cache: true,
143 parallel: false,
144 publicFolder: 'public'
145 }
146 )
147
148 const [error, result] = Struct.validate(config)
149
150 if (error) {
151 throw error
152 }
153
154 result.output.fileNames = Object.assign(
155 getFileNames({ useHash: api.isProd, format: result.output.format }),
156 result.output.fileNames
157 )
158
159 // Always disable cache in test mode
160 if (process.env.NODE_ENV === 'test') {
161 result.cache = false
162 }
163
164 api.logger.debug('Validated config', result)
165
166 return result
167}