UNPKG

5.12 kBJavaScriptView Raw
1const path = require('path')
2const findBabelConfig = require('find-babel-config')
3const findPostcssConfig = require('postcss-load-config')
4const logger = require('@poi/logger')
5const inferHTML = require('./utils/inferHTML')
6const readProjectPkg = require('./utils/readProjectPkg')
7const normalizeEntry = require('./utils/normalizeEntry')
8const getFilename = require('./utils/getFilename')
9const getPublicPath = require('./utils/getPublicPath')
10const getHotEntry = require('./utils/getHotEntry')
11const getExternals = require('./utils/getExternals')
12
13async function handleBabel(options) {
14 const { file } = await findBabelConfig(process.cwd(), 2)
15
16 if (file) {
17 // If root babel config file is found
18 // We set `babelrc` to the its path
19 // To prevent `babel-loader` from loading it again
20 logger.debug('babel config location', file)
21 } else {
22 // If not found
23 // We set `babelrc` to `false` for the same reason
24 options.config.babelrc = false
25 }
26
27 if (options.config.babelrc === false) {
28 // Use our default preset when no babelrc was specified
29 options.config.presets = [
30 [require.resolve('babel-preset-poi'), { jsx: options.jsx }]
31 ]
32 }
33
34 options.config.cacheDirectory = true
35
36 return options
37}
38
39function handleHTML({ html, minimize, env }) {
40 if (html === false) return false
41
42 const htmls = Array.isArray(html) ? html : [html || {}]
43
44 const defaultHtmlOption = Object.assign({ env }, inferHTML())
45
46 return htmls.map((h, i) => {
47 return Object.assign(
48 {
49 minify: {
50 collapseWhitespace: minimize,
51 minifyCSS: minimize,
52 minifyJS: minimize
53 }
54 },
55 defaultHtmlOption,
56 h
57 )
58 })
59}
60
61module.exports = async ({ options, command, env }) => {
62 options = Object.assign(
63 {
64 entry: readProjectPkg().main || 'index.js',
65 cwd: process.cwd(),
66 vue: {},
67 css: {},
68 hash: !options.format && command === 'build'
69 },
70 options
71 )
72
73 options.devServer = Object.assign(
74 {
75 host: options.host || process.env.HOST || '0.0.0.0',
76 port: options.port || process.env.PORT || 4000
77 },
78 options.devServer
79 )
80 options.babel = Object.assign(
81 {
82 jsx: 'react',
83 config: {}
84 },
85 options.babel
86 )
87
88 options.entry = normalizeEntry(options.entry)
89 options.filename = getFilename(options.hash, options.filename)
90 options.outDir = path.resolve(options.outDir || 'dist')
91 options.publicPath = getPublicPath(command, options.publicPath)
92 options.hotReload = options.hotReload !== false && command === 'develop'
93 options.hotEntry = getHotEntry(options.hotEntry)
94 options.minimize =
95 typeof options.minimize === 'boolean'
96 ? options.minimize
97 : command === 'build'
98 options.html =
99 options.format || command === 'test'
100 ? false
101 : handleHTML({
102 minimize: options.minimize,
103 env,
104 html: options.html
105 })
106 options.sourceMap = options.format
107 ? false
108 : options.sourceMap === false || typeof options.sourceMap === 'string'
109 ? options.sourceMap
110 : command === 'build'
111 ? 'source-map'
112 : command === 'test'
113 ? 'inline-source-map'
114 : 'eval-source-map'
115
116 options.externals = getExternals(options).concat(options.externals || [])
117 options.babel = await handleBabel(options.babel)
118
119 if (options.postcss === undefined) {
120 const postcssConfig = await findPostcssConfig({}, options.cwd, {
121 argv: false
122 }).catch(err => {
123 if (err.message.includes('No PostCSS Config found')) {
124 // Return empty options for PostCSS
125 return {}
126 }
127 throw err
128 })
129
130 if (postcssConfig.file) {
131 logger.debug('postcss config location', postcssConfig.file)
132
133 // Only feed the config path to postcss-loader
134 // In order to let postcss-loader ask webpack to watch it
135 options.postcss = {
136 config: {
137 path: postcssConfig.file
138 }
139 }
140 } else {
141 // No PostCSS config file was found
142 // Set `plugins` to an empty array so `postcss-loader` won't try to find config file again
143 options.postcss = {
144 plugins: []
145 }
146 }
147 }
148
149 options.postcss = options.postcss || {}
150
151 options.css = {
152 minimize: options.minimize,
153 extract:
154 typeof options.css.extract === 'boolean'
155 ? options.css.extract
156 : command === 'build',
157 extractLoader: options.css.extractLoader,
158 sourceMap:
159 typeof options.css.sourceMap === 'boolean'
160 ? options.css.sourceMap
161 : command === 'develop' && Boolean(options.sourceMap), // Only enable CSS sourceMap in dev mode
162 postcss: options.postcss,
163 cssModules: options.css.modules,
164 styleLoader: 'vue-style-loader',
165 filename: options.filename.css,
166 chunkFilename: options.filename.chunk.replace(/\.js$/, '.css')
167 }
168
169 if (options.entry === undefined && !options.format) {
170 const mainField = readProjectPkg().main
171 if (mainField) {
172 logger.debug('webpack', 'Using main field in package.json as entry point')
173 options.entry = mainField
174 }
175 }
176
177 return options
178}