1 | const { superstruct } = require('superstruct')
|
2 | const getFileNames = require('./getFileNames')
|
3 |
|
4 | module.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 |
|
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 | }
|