UNPKG

18.3 kBJavaScriptView Raw
1"use strict";
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports.default = getConfig;
7
8var _webpack = _interopRequireDefault(require("webpack"));
9
10var _caseSensitivePathsWebpackPlugin = _interopRequireDefault(require("case-sensitive-paths-webpack-plugin"));
11
12var _systemBellWebpackPlugin = _interopRequireDefault(require("system-bell-webpack-plugin"));
13
14var _extractTextWebpackPlugin = _interopRequireDefault(require("extract-text-webpack-plugin"));
15
16var _webpackManifestPlugin = _interopRequireDefault(require("webpack-manifest-plugin"));
17
18var _swPrecacheWebpackPlugin = _interopRequireDefault(require("sw-precache-webpack-plugin"));
19
20var _autoprefixer = _interopRequireDefault(require("autoprefixer"));
21
22var _path = require("path");
23
24var _fs = require("fs");
25
26var _eslintFormatter = _interopRequireDefault(require("react-dev-utils/eslintFormatter"));
27
28var _assert = _interopRequireDefault(require("assert"));
29
30var _deprecate = _interopRequireDefault(require("deprecate"));
31
32var _webpackBundleAnalyzer = require("webpack-bundle-analyzer");
33
34var _copyWebpackPlugin = _interopRequireDefault(require("copy-webpack-plugin"));
35
36var _htmlWebpackPlugin = _interopRequireDefault(require("html-webpack-plugin"));
37
38var _progressBarWebpackPlugin = _interopRequireDefault(require("progress-bar-webpack-plugin"));
39
40var _resolve = require("resolve");
41
42var _forkTsCheckerWebpackPlugin = _interopRequireDefault(require("fork-ts-checker-webpack-plugin"));
43
44var _hardSourceWebpackPlugin = _interopRequireDefault(require("hard-source-webpack-plugin"));
45
46var _uglifyJS = _interopRequireDefault(require("./defaultConfigs/uglifyJS"));
47
48var _babel = _interopRequireDefault(require("./defaultConfigs/babel"));
49
50var _browsers = _interopRequireDefault(require("./defaultConfigs/browsers"));
51
52var _stringifyObject = _interopRequireDefault(require("./stringifyObject"));
53
54var _normalizeTheme = _interopRequireDefault(require("./normalizeTheme"));
55
56var _applyWebpackConfig = require("./applyWebpackConfig");
57
58var _readRc = _interopRequireDefault(require("./readRc"));
59
60var _utils = require("./utils");
61
62var _es5ImcompatibleVersions = require("./es5ImcompatibleVersions");
63
64function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
65
66function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; }
67
68function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
69
70const _require = require('awesome-typescript-loader'),
71 TsConfigPathsPlugin = _require.TsConfigPathsPlugin; // eslint-disable-line
72
73
74const debug = require('debug')('af-webpack:getConfig');
75
76if (process.env.DISABLE_TSLINT) {
77 (0, _deprecate.default)('DISABLE_TSLINT is deprecated, use TSLINT=none instead');
78}
79
80if (process.env.DISABLE_ESLINT) {
81 (0, _deprecate.default)('DISABLE_ESLINT is deprecated, use ESLINT=none instead');
82}
83
84if (process.env.NO_COMPRESS) {
85 (0, _deprecate.default)('NO_COMPRESS is deprecated, use COMPRESS=none instead');
86}
87
88function getConfig(opts = {}) {
89 (0, _assert.default)(opts.cwd, 'opts.cwd must be specified');
90 const isDev = process.env.NODE_ENV === 'development';
91 const theme = (0, _normalizeTheme.default)(opts.theme);
92 const postcssOptions = {
93 // Necessary for external CSS imports to work
94 // https://github.com/facebookincubator/create-react-app/issues/2677
95 ident: 'postcss',
96 plugins: () => [require('postcss-flexbugs-fixes'), // eslint-disable-line
97 (0, _autoprefixer.default)({
98 browsers: opts.browserslist || _browsers.default,
99 flexbox: 'no-2009'
100 }), ...(opts.extraPostCSSPlugins ? opts.extraPostCSSPlugins : [])]
101 };
102 const cssModulesConfig = {
103 modules: true,
104 localIdentName: isDev ? '[name]__[local]___[hash:base64:5]' : '[local]___[hash:base64:5]'
105 };
106
107 const lessOptions = _objectSpread({
108 modifyVars: theme
109 }, opts.lessLoaderOptions || {});
110
111 const cssOptions = _objectSpread({
112 importLoaders: 1
113 }, isDev ? {} : {
114 minimize: !(process.env.CSS_COMPRESS === 'none' || process.env.COMPRESS === 'none' || process.env.NO_COMPRESS) ? {
115 // ref: https://github.com/umijs/umi/issues/164
116 minifyFontValues: false
117 } : false,
118 sourceMap: !opts.disableCSSSourceMap
119 }, opts.cssLoaderOptions || {});
120
121 function getCSSLoader(opts = {}) {
122 const cssModules = opts.cssModules,
123 less = opts.less,
124 sass = opts.sass,
125 sassOptions = opts.sassOptions;
126 let hasSassLoader = true;
127
128 try {
129 require.resolve('sass-loader');
130 } catch (e) {
131 hasSassLoader = false;
132 }
133
134 return [require.resolve('style-loader'), {
135 loader: require.resolve('css-loader'),
136 options: _objectSpread({}, cssOptions, cssModules ? cssModulesConfig : {})
137 }, {
138 loader: require.resolve('postcss-loader'),
139 options: postcssOptions
140 }, ...(less ? [{
141 loader: require.resolve('less-loader'),
142 options: lessOptions
143 }] : []), ...(sass && hasSassLoader ? [{
144 loader: require.resolve('sass-loader'),
145 options: sassOptions
146 }] : [])];
147 }
148
149 function exclude(filePath) {
150 if (/node_modules/.test(filePath)) {
151 return true;
152 }
153
154 if (opts.cssModulesWithAffix) {
155 if (/\.module\.(css|less|sass|scss)$/.test(filePath)) return true;
156 }
157
158 if (opts.cssModulesExcludes) {
159 var _iteratorNormalCompletion = true;
160 var _didIteratorError = false;
161 var _iteratorError = undefined;
162
163 try {
164 for (var _iterator = opts.cssModulesExcludes[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
165 const exclude = _step.value;
166 if (filePath.indexOf(exclude) > -1) return true;
167 }
168 } catch (err) {
169 _didIteratorError = true;
170 _iteratorError = err;
171 } finally {
172 try {
173 if (!_iteratorNormalCompletion && _iterator.return != null) {
174 _iterator.return();
175 }
176 } finally {
177 if (_didIteratorError) {
178 throw _iteratorError;
179 }
180 }
181 }
182 }
183 }
184
185 const cssRules = [...(opts.cssModulesExcludes ? opts.cssModulesExcludes.map(file => {
186 return {
187 test(filePath) {
188 return filePath.indexOf(file) > -1;
189 },
190
191 use: getCSSLoader({
192 less: (0, _path.extname)(file).toLowerCase() === '.less',
193 sass: (0, _path.extname)(file).toLowerCase() === '.sass' || (0, _path.extname)(file).toLowerCase() === '.scss',
194 sassOptions: opts.sass
195 })
196 };
197 }) : []), ...(opts.cssModulesWithAffix ? [{
198 test: /\.module\.css$/,
199 use: getCSSLoader({
200 cssModules: true
201 })
202 }, {
203 test: /\.module\.less$/,
204 use: getCSSLoader({
205 cssModules: true,
206 less: true
207 })
208 }, {
209 test: /\.module\.(sass|scss)$/,
210 use: getCSSLoader({
211 cssModules: true,
212 sass: true,
213 sassOptions: opts.sass
214 })
215 }] : []), {
216 test: /\.css$/,
217 exclude,
218 use: getCSSLoader({
219 cssModules: !opts.disableCSSModules
220 })
221 }, {
222 test: /\.css$/,
223 include: /node_modules/,
224 use: getCSSLoader()
225 }, {
226 test: /\.less$/,
227 exclude,
228 use: getCSSLoader({
229 cssModules: !opts.disableCSSModules,
230 less: true
231 })
232 }, {
233 test: /\.less$/,
234 include: /node_modules/,
235 use: getCSSLoader({
236 less: true
237 })
238 }, {
239 test: /\.(sass|scss)$/,
240 exclude,
241 use: getCSSLoader({
242 cssModules: !opts.disableCSSModules,
243 sass: true,
244 sassOptions: opts.sass
245 })
246 }, {
247 test: /\.(sass|scss)$/,
248 include: /node_modules/,
249 use: getCSSLoader({
250 sass: true,
251 sassOptions: opts.sass
252 })
253 }]; // 生成环境下用 ExtractTextPlugin 提取出来
254
255 if (!isDev) {
256 cssRules.forEach(rule => {
257 rule.use = _extractTextWebpackPlugin.default.extract({
258 use: rule.use.slice(1)
259 });
260 });
261 } // TODO: 根据 opts.hash 自动处理这里的 filename
262
263
264 const commonsPlugins = (opts.commons || []).map(common => {
265 return new _webpack.default.optimize.CommonsChunkPlugin(common);
266 }); // Declare outputPath here for reuse
267
268 const outputPath = opts.outputPath ? (0, _path.resolve)(opts.cwd, opts.outputPath) : (0, _path.resolve)(opts.cwd, 'dist'); // Copy files in public to outputPath
269
270 const copyPlugins = opts.copy ? [new _copyWebpackPlugin.default(opts.copy)] : [];
271
272 if ((0, _fs.existsSync)((0, _path.resolve)(opts.cwd, 'public'))) {
273 copyPlugins.push(new _copyWebpackPlugin.default([{
274 from: (0, _path.resolve)(opts.cwd, 'public'),
275 to: outputPath,
276 toType: 'dir'
277 }], {
278 ignore: ['**/.*']
279 }));
280 } // js 和 css 采用不同的 hash 算法
281
282
283 const jsHash = !isDev && opts.hash ? '.[chunkhash:8]' : '';
284 const cssHash = !isDev && opts.hash ? '.[contenthash:8]' : '';
285
286 const babelOptions = _objectSpread({}, opts.babel || _babel.default, {
287 cacheDirectory: process.env.BABEL_CACHE !== 'none',
288 babelrc: !!process.env.BABELRC
289 });
290
291 babelOptions.plugins = [...(babelOptions.plugins || []), ...(opts.disableDynamicImport ? [require.resolve('babel-plugin-dynamic-import-node-sync')] : [])];
292 const babelUse = [{
293 loader: require('path').join(__dirname, 'debugLoader.js') // eslint-disable-line
294
295 }, {
296 loader: require.resolve('babel-loader'),
297 options: babelOptions
298 }];
299 const babelOptionsDeps = {
300 presets: [[require.resolve('babel-preset-umi'), {
301 disableTransform: true
302 }]],
303 cacheDirectory: process.env.BABEL_CACHE !== 'none',
304 babelrc: !!process.env.BABELRC
305 };
306 const babelUseDeps = [{
307 loader: require('path').join(__dirname, 'debugLoader.js') // eslint-disable-line
308
309 }, {
310 loader: require.resolve('babel-loader'),
311 options: babelOptionsDeps
312 }];
313 const eslintOptions = {
314 formatter: _eslintFormatter.default,
315 baseConfig: {
316 extends: [require.resolve('eslint-config-umi')]
317 },
318 ignore: false,
319 eslintPath: require.resolve('eslint'),
320 useEslintrc: false
321 }; // 用用户的 eslint
322
323 try {
324 const _require2 = require((0, _path.resolve)('package.json')),
325 dependencies = _require2.dependencies,
326 devDependencies = _require2.devDependencies; // eslint-disable-line
327
328
329 if (dependencies.eslint || devDependencies.eslint) {
330 const eslintPath = (0, _resolve.sync)('eslint', {
331 basedir: opts.cwd
332 });
333 eslintOptions.eslintPath = eslintPath;
334 debug(`use user's eslint bin: ${eslintPath}`);
335 }
336 } catch (e) {} // do nothing
337 // 读用户的 eslintrc
338
339
340 const userEslintRulePath = (0, _path.resolve)(opts.cwd, '.eslintrc');
341
342 if ((0, _fs.existsSync)(userEslintRulePath)) {
343 try {
344 const userRc = (0, _readRc.default)(userEslintRulePath);
345 debug(`userRc: ${JSON.stringify(userRc)}`);
346
347 if (userRc.extends) {
348 debug(`use user's .eslintrc: ${userEslintRulePath}`);
349 eslintOptions.useEslintrc = true;
350 eslintOptions.baseConfig = false;
351 eslintOptions.ignore = true;
352 } else {
353 debug(`extend with user's .eslintrc: ${userEslintRulePath}`);
354 eslintOptions.baseConfig = _objectSpread({}, eslintOptions.baseConfig, userRc);
355 }
356 } catch (e) {
357 debug(e);
358 }
359 }
360
361 const extraBabelIncludes = opts.extraBabelIncludes || [];
362
363 if (opts.es5ImcompatibleVersions) {
364 extraBabelIncludes.push(a => {
365 if (a.indexOf('node_modules') === -1) return false;
366 const pkgPath = (0, _es5ImcompatibleVersions.getPkgPath)(a);
367 return (0, _es5ImcompatibleVersions.shouldTransform)(pkgPath);
368 });
369 }
370
371 const config = {
372 bail: !isDev,
373 devtool: opts.devtool || undefined,
374 entry: opts.entry || null,
375 output: {
376 path: outputPath,
377 // Add /* filename */ comments to generated require()s in the output.
378 pathinfo: isDev,
379 filename: `[name]${jsHash}.js`,
380 publicPath: opts.publicPath || undefined,
381 chunkFilename: `[name]${jsHash}.async.js`
382 },
383 resolve: {
384 modules: ['node_modules', (0, _path.resolve)(__dirname, '../node_modules'), ...(opts.extraResolveModules || [])],
385 extensions: [...(opts.extraResolveExtensions || []), '.web.js', '.web.jsx', '.web.ts', '.web.tsx', '.js', '.json', '.jsx', '.ts', '.tsx'],
386 alias: _objectSpread({}, opts.alias),
387 plugins: process.env.TS_CONFIG_PATHS_PLUGIN && process.env.TS_CONFIG_PATHS_PLUGIN !== 'none' ? [new TsConfigPathsPlugin()] : []
388 },
389 module: {
390 rules: [...(process.env.DISABLE_TSLINT || process.env.TSLINT === 'none' ? [] : [{
391 test: /\.tsx?$/,
392 include: opts.cwd,
393 exclude: /node_modules/,
394 enforce: 'pre',
395 use: [{
396 options: {
397 emitErrors: true // formatter: eslintFormatter,
398
399 },
400 loader: require.resolve('tslint-loader')
401 }]
402 }]), ...(process.env.DISABLE_ESLINT || process.env.ESLINT === 'none' ? [] : [{
403 test: /\.(js|jsx)$/,
404 include: opts.cwd,
405 exclude: /node_modules/,
406 enforce: 'pre',
407 use: [{
408 options: eslintOptions,
409 loader: require.resolve('eslint-loader')
410 }]
411 }]), {
412 exclude: [/\.(html|ejs)$/, /\.json$/, /\.(js|jsx|ts|tsx)$/, /\.(css|less|scss|sass)$/, ...(opts.urlLoaderExcludes || [])],
413 loader: require.resolve('url-loader'),
414 options: {
415 limit: 10000,
416 name: 'static/[name].[hash:8].[ext]'
417 }
418 }, {
419 test: /\.js$/,
420 include: opts.cwd,
421 exclude: /node_modules/,
422 use: babelUse
423 }, {
424 test: /\.jsx$/,
425 include: opts.cwd,
426 use: babelUse
427 }, {
428 test: /\.(ts|tsx)$/,
429 include: opts.cwd,
430 exclude: /node_modules/,
431 use: [...babelUse, {
432 loader: require.resolve('awesome-typescript-loader'),
433 options: _objectSpread({
434 configFileName: opts.tsConfigFile || (0, _path.join)(opts.cwd, 'tsconfig.json'),
435 transpileOnly: true
436 }, opts.typescript || {})
437 }]
438 }, ...extraBabelIncludes.map(include => {
439 return {
440 test: /\.(js|jsx)$/,
441 include: typeof include === 'string' ? (0, _path.join)(opts.cwd, include) : include,
442 use: babelUseDeps
443 };
444 }), {
445 test: /\.html$/,
446 loader: require.resolve('file-loader'),
447 options: {
448 name: '[name].[ext]'
449 }
450 }, ...cssRules]
451 },
452 plugins: [...(isDev ? [new _webpack.default.HotModuleReplacementPlugin(), // Disable this plugin since it causes 100% cpu when have lost deps
453 // new WatchMissingNodeModulesPlugin(join(opts.cwd, 'node_modules')),
454 new _systemBellWebpackPlugin.default(), ...(process.env.HARD_SOURCE && process.env.HARD_SOURCE !== 'none' ? [new _hardSourceWebpackPlugin.default()] : [])].concat(opts.devtool ? [] : [new _webpack.default.SourceMapDevToolPlugin({
455 columns: false,
456 moduleFilenameTemplate: info => {
457 if (/\/koi-pkgs\/packages/.test(info.absoluteResourcePath) || /packages\/koi-core/.test(info.absoluteResourcePath) || /webpack\/bootstrap/.test(info.absoluteResourcePath) || /\/node_modules\//.test(info.absoluteResourcePath)) {
458 return `internal:///${info.absoluteResourcePath}`;
459 }
460
461 return (0, _path.resolve)(info.absoluteResourcePath).replace(/\\/g, '/');
462 }
463 })]) : [...(process.env.__FROM_TEST ? [] : [new _webpack.default.HashedModuleIdsPlugin()]), new _webpack.default.optimize.ModuleConcatenationPlugin(), new _extractTextWebpackPlugin.default({
464 filename: `[name]${cssHash}.css`,
465 allChunks: true
466 }), ...(opts.serviceworker ? [new _swPrecacheWebpackPlugin.default(_objectSpread({
467 filename: 'service-worker.js',
468 minify: !(process.env.NO_COMPRESS || process.env.COMPRESS === 'none'),
469 staticFileGlobsIgnorePatterns: [/\.map$/, /asset-manifest\.json$/]
470 }, opts.serviceworker))] : []), ...(opts.manifest ? [new _webpackManifestPlugin.default(_objectSpread({
471 fileName: 'manifest.json'
472 }, opts.manifest))] : [])]), ...(isDev || process.env.NO_COMPRESS || process.env.COMPRESS === 'none' ? [] : [new _webpack.default.optimize.UglifyJsPlugin(_objectSpread({}, _uglifyJS.default, opts.devtool ? {
473 sourceMap: true
474 } : {}))]), new _webpack.default.DefinePlugin(_objectSpread({
475 'process.env.NODE_ENV': JSON.stringify( // eslint-disable-line
476 isDev ? 'development' : 'production'),
477 // eslint-disable-line
478 'process.env.HMR': process.env.HMR
479 }, process.env.SOCKET_SERVER ? {
480 'process.env.SOCKET_SERVER': JSON.stringify(process.env.SOCKET_SERVER)
481 } : {}, (0, _stringifyObject.default)(opts.define || {}))), ...(opts.html ? [new _htmlWebpackPlugin.default(opts.html)] : []), new _caseSensitivePathsWebpackPlugin.default(), new _webpack.default.LoaderOptionsPlugin({
482 options: {
483 context: __dirname
484 }
485 }), new _progressBarWebpackPlugin.default(), ...(process.env.TS_TYPECHECK ? [new _forkTsCheckerWebpackPlugin.default()] : []), ...(opts.ignoreMomentLocale ? [new _webpack.default.IgnorePlugin(/^\.\/locale$/, /moment$/)] : []), ...commonsPlugins, ...copyPlugins, ...(process.env.ANALYZE ? [new _webpackBundleAnalyzer.BundleAnalyzerPlugin({
486 analyzerMode: 'server',
487 analyzerPort: process.env.ANALYZE_PORT || 8888,
488 openAnalyzer: true
489 })] : [])],
490 externals: opts.externals,
491 node: {
492 dgram: 'empty',
493 fs: 'empty',
494 net: 'empty',
495 tls: 'empty',
496 child_process: 'empty'
497 },
498 performance: isDev ? {
499 hints: false
500 } : {}
501 };
502
503 if (process.env.PUBLIC_PATH) {
504 config.output.publicPath = `${(0, _utils.stripLastSlash)(process.env.PUBLIC_PATH)}/`;
505 }
506
507 return (0, _applyWebpackConfig.applyWebpackConfig)(opts.cwd, config);
508}
\No newline at end of file