1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 | "use strict";
|
8 |
|
9 | const fs = require("fs");
|
10 | const autoprefixer = require("autoprefixer");
|
11 | const path = require("path");
|
12 | const webpack = require("webpack");
|
13 | const HtmlWebpackPlugin = require("html-webpack-plugin");
|
14 | const ExtractTextPlugin = require("extract-text-webpack-plugin");
|
15 | const ManifestPlugin = require("webpack-manifest-plugin");
|
16 | const InterpolateHtmlPlugin = require("react-dev-utils/InterpolateHtmlPlugin");
|
17 | const SWPrecacheWebpackPlugin = require("sw-precache-webpack-plugin");
|
18 | const eslintFormatter = require("react-dev-utils/eslintFormatter");
|
19 | const ModuleScopePlugin = require("react-dev-utils/ModuleScopePlugin");
|
20 | const paths = require("./paths");
|
21 | const getClientEnvironment = require("./env");
|
22 | const os = require("os");
|
23 | const HappyPack = require("happypack");
|
24 | const happyThreadPool = HappyPack.ThreadPool({ size: os.cpus().length });
|
25 | const AutoDllPlugin = require("autodll-webpack-plugin");
|
26 | const ParallelUglifyPlugin = require("webpack-parallel-uglify-plugin");
|
27 |
|
28 | const publicPath = paths.servedPath;
|
29 | const shouldUseRelativeAssetPaths = publicPath === "./";
|
30 | const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== "false";
|
31 | const publicUrl = publicPath.slice(0, -1);
|
32 | const env = getClientEnvironment(publicUrl);
|
33 |
|
34 | if (env.stringified["process.env"].NODE_ENV !== '"production"') {
|
35 | throw new Error("Production builds must have NODE_ENV=production.");
|
36 | }
|
37 |
|
38 | const cssFilename = "static/css/[name].[contenthash:8].css";
|
39 |
|
40 | const extractTextPluginOptions = shouldUseRelativeAssetPaths
|
41 | ?
|
42 | { publicPath: Array(cssFilename.split("/").length).join("../") }
|
43 | : {};
|
44 |
|
45 | const alias =
|
46 | (fs.existsSync(paths.appConfig) && require(paths.appConfig).alias) || {};
|
47 |
|
48 | for (let i in alias) {
|
49 | alias[i] = paths.appSrc + alias[i];
|
50 | }
|
51 |
|
52 |
|
53 | const modifyVars =
|
54 | (fs.existsSync(paths.appConfig) && require(paths.appConfig).modifyVars) || {};
|
55 | const moreLoaders =
|
56 | (fs.existsSync(paths.appConfig) && require(paths.appConfig).loaders) || [];
|
57 | const moredPlugins =
|
58 | (fs.existsSync(paths.appConfig) && require(paths.appConfig).prodPlugins) ||
|
59 | [];
|
60 | const tempVendors = require(paths.appConfig).vendors || [];
|
61 |
|
62 | let vendors = {
|
63 | vendors: []
|
64 | };
|
65 | if (Array.isArray(tempVendors)) {
|
66 | vendors = {
|
67 | vendors: tempVendors
|
68 | };
|
69 | }
|
70 | if (tempVendors.toString() === "[object Object]") {
|
71 | vendors = tempVendors;
|
72 | }
|
73 |
|
74 |
|
75 | module.exports = {
|
76 | bail: true,
|
77 | devtool: shouldUseSourceMap ? "source-map" : false,
|
78 | entry: [require.resolve("./polyfills"), paths.appIndexJs],
|
79 | output: {
|
80 | path: paths.appBuild,
|
81 | filename: "static/js/[name].[chunkhash:8].js",
|
82 | chunkFilename: "static/js/[name].[chunkhash:8].chunk.js",
|
83 | publicPath: publicPath,
|
84 | devtoolModuleFilenameTemplate: info =>
|
85 | path.relative(paths.appSrc, info.absoluteResourcePath).replace(/\\/g, "/")
|
86 | },
|
87 | resolve: {
|
88 | modules: ["node_modules", paths.appNodeModules].concat(
|
89 | process.env.NODE_PATH.split(path.delimiter).filter(Boolean)
|
90 | ),
|
91 | extensions: [
|
92 | ".web.js",
|
93 | ".js",
|
94 | ".json",
|
95 | ".web.jsx",
|
96 | ".jsx",
|
97 | ".web.ts",
|
98 | ".ts",
|
99 | ".web.tsx",
|
100 | ".tsx"
|
101 | ],
|
102 | alias: Object.assign(
|
103 |
|
104 | {},
|
105 | {
|
106 | "babel-runtime": path.dirname(
|
107 | require.resolve("babel-runtime/package.json")
|
108 | ),
|
109 | "react-native": "react-native-web"
|
110 | },
|
111 | alias
|
112 | ),
|
113 | plugins: [new ModuleScopePlugin(paths.appSrc, [paths.appPackageJson])]
|
114 | },
|
115 | module: {
|
116 | strictExportPresence: true,
|
117 | rules: [
|
118 | {
|
119 | test: /\.(js|jsx)$/,
|
120 | enforce: "pre",
|
121 | use: [
|
122 | {
|
123 | options: {
|
124 | formatter: eslintFormatter,
|
125 | eslintPath: require.resolve("eslint")
|
126 | },
|
127 | loader: require.resolve("eslint-loader")
|
128 | }
|
129 | ],
|
130 | include: paths.appSrc
|
131 | },
|
132 | {
|
133 | test: /\.(ts|tsx)$/,
|
134 | loader: require.resolve("tslint-loader"),
|
135 | enforce: "pre",
|
136 | include: paths.appSrc
|
137 | },
|
138 | {
|
139 | oneOf: [
|
140 | {
|
141 | test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
|
142 | loader: require.resolve("url-loader"),
|
143 | options: {
|
144 | limit: 10000,
|
145 | name: "static/media/[name].[hash:8].[ext]"
|
146 | }
|
147 | },
|
148 | {
|
149 | test: /\.(js|jsx)$/,
|
150 | include: paths.appSrc,
|
151 | loaders: ["happypack/loader"]
|
152 | },
|
153 | {
|
154 | test: /\.(ts|tsx)$/,
|
155 | include: paths.appSrc,
|
156 | loader: [
|
157 | require.resolve("babel-loader"),
|
158 | require.resolve("ts-loader")
|
159 | ]
|
160 | },
|
161 | {
|
162 | test: /\.css$/,
|
163 | loader: ExtractTextPlugin.extract(
|
164 | Object.assign(
|
165 | {
|
166 | fallback: require.resolve("style-loader"),
|
167 | use: [
|
168 | {
|
169 | loader: require.resolve("css-loader"),
|
170 | options: {
|
171 | importLoaders: 1,
|
172 | minimize: true,
|
173 | sourceMap: shouldUseSourceMap
|
174 | }
|
175 | },
|
176 | {
|
177 | loader: require.resolve("postcss-loader"),
|
178 | options: {
|
179 | ident: "postcss",
|
180 | plugins: () => [
|
181 | require("postcss-flexbugs-fixes"),
|
182 | autoprefixer({
|
183 | browsers: [
|
184 | ">1%",
|
185 | "last 4 versions",
|
186 | "Firefox ESR",
|
187 | "not ie < 9"
|
188 | ],
|
189 | flexbox: "no-2009"
|
190 | })
|
191 | ]
|
192 | }
|
193 | }
|
194 | ]
|
195 | },
|
196 | extractTextPluginOptions
|
197 | )
|
198 | )
|
199 | },
|
200 |
|
201 | {
|
202 |
|
203 | test: /\.module\.less$/,
|
204 | loader: ExtractTextPlugin.extract(
|
205 | Object.assign(
|
206 | {
|
207 | fallback: require.resolve("style-loader"),
|
208 | use: [
|
209 | {
|
210 | loader: require.resolve("css-loader"),
|
211 | options: {
|
212 | importLoaders: 1,
|
213 | minimize: true,
|
214 | sourceMap: shouldUseSourceMap,
|
215 | modules: true,
|
216 | localIdentName: "[local]___[hash:base64:5]"
|
217 | }
|
218 | },
|
219 | {
|
220 | loader: require.resolve("postcss-loader"),
|
221 | options: {
|
222 | ident: "postcss",
|
223 | plugins: () => [
|
224 | require("postcss-flexbugs-fixes"),
|
225 | autoprefixer({
|
226 | browsers: [
|
227 | ">1%",
|
228 | "last 4 versions",
|
229 | "Firefox ESR",
|
230 | "not ie < 9"
|
231 | ],
|
232 | flexbox: "no-2009"
|
233 | })
|
234 | ]
|
235 | }
|
236 | },
|
237 | {
|
238 | loader: require.resolve("less-loader"),
|
239 | options: {
|
240 | modifyVars: modifyVars
|
241 | }
|
242 | }
|
243 | ]
|
244 | },
|
245 | extractTextPluginOptions
|
246 | )
|
247 | )
|
248 | },
|
249 |
|
250 | {
|
251 |
|
252 | test: /\.less$/,
|
253 | loader: ExtractTextPlugin.extract(
|
254 | Object.assign(
|
255 | {
|
256 | fallback: require.resolve("style-loader"),
|
257 | use: [
|
258 | {
|
259 | loader: require.resolve("css-loader"),
|
260 | options: {
|
261 | importLoaders: 1,
|
262 | minimize: true,
|
263 | sourceMap: shouldUseSourceMap
|
264 | }
|
265 | },
|
266 | {
|
267 | loader: require.resolve("postcss-loader"),
|
268 | options: {
|
269 | ident: "postcss",
|
270 | plugins: () => [
|
271 | require("postcss-flexbugs-fixes"),
|
272 | autoprefixer({
|
273 | browsers: [
|
274 | ">1%",
|
275 | "last 4 versions",
|
276 | "Firefox ESR",
|
277 | "not ie < 9"
|
278 | ],
|
279 | flexbox: "no-2009"
|
280 | })
|
281 | ]
|
282 | }
|
283 | },
|
284 | {
|
285 | loader: require.resolve("less-loader"),
|
286 | options: {
|
287 | modifyVars: modifyVars
|
288 | }
|
289 | }
|
290 | ]
|
291 | },
|
292 | extractTextPluginOptions
|
293 | )
|
294 | )
|
295 | },
|
296 | {
|
297 | loader: require.resolve("file-loader"),
|
298 | exclude: [/\.js$/, /\.html$/, /\.json$/],
|
299 | options: {
|
300 | name: "static/media/[name].[hash:8].[ext]"
|
301 | }
|
302 | }
|
303 | ].concat(moreLoaders)
|
304 | }
|
305 | ]
|
306 | },
|
307 | plugins: [
|
308 |
|
309 | new HappyPack({
|
310 | threadPool: happyThreadPool,
|
311 | verbose: false,
|
312 | loaders: [
|
313 | {
|
314 | loader: require.resolve("babel-loader"),
|
315 | options: {
|
316 | compact: true
|
317 | }
|
318 | }
|
319 | ]
|
320 | }),
|
321 | new AutoDllPlugin({
|
322 | inject: true,
|
323 | path: "/static/js",
|
324 | filename: "[name].dll.js",
|
325 | entry: vendors,
|
326 | plugins: [
|
327 | new webpack.DefinePlugin({
|
328 | "process.env": {
|
329 | NODE_ENV: JSON.stringify("production")
|
330 | }
|
331 | }),
|
332 | new ParallelUglifyPlugin({
|
333 | cacheDir: ".cache/",
|
334 | uglifyJS: {
|
335 | compress: {
|
336 |
|
337 | drop_console: true,
|
338 | warnings: false,
|
339 | comparisons: false
|
340 | },
|
341 | output: {
|
342 | comments: false,
|
343 | ascii_only: true
|
344 | }
|
345 | }
|
346 | })
|
347 | ]
|
348 | }),
|
349 | new InterpolateHtmlPlugin(env.raw),
|
350 | new HtmlWebpackPlugin({
|
351 | inject: true,
|
352 | template: paths.appHtml,
|
353 | minify: {
|
354 | removeComments: true,
|
355 | collapseWhitespace: true,
|
356 | removeRedundantAttributes: true,
|
357 | useShortDoctype: true,
|
358 | removeEmptyAttributes: true,
|
359 | removeStyleLinkTypeAttributes: true,
|
360 | keepClosingSlash: true,
|
361 | minifyJS: true,
|
362 | minifyCSS: true,
|
363 | minifyURLs: true
|
364 | }
|
365 | }),
|
366 | new webpack.DefinePlugin(env.stringified),
|
367 | new ParallelUglifyPlugin({
|
368 | cacheDir: ".cache/",
|
369 | sourceMap: shouldUseSourceMap,
|
370 | uglifyJS: {
|
371 | compress: {
|
372 | warnings: false,
|
373 |
|
374 | drop_console: true,
|
375 | comparisons: false
|
376 | },
|
377 | output: {
|
378 | comments: false,
|
379 | ascii_only: true
|
380 | }
|
381 | }
|
382 | }),
|
383 | new ExtractTextPlugin({
|
384 | filename: cssFilename,
|
385 | allChunks: true
|
386 | }),
|
387 | new ManifestPlugin({
|
388 | fileName: "asset-manifest.json"
|
389 | }),
|
390 | new SWPrecacheWebpackPlugin({
|
391 | dontCacheBustUrlsMatching: /\.\w{8}\./,
|
392 | filename: "service-worker.js",
|
393 | logger(message) {
|
394 | if (message.indexOf("Total precache size is") === 0) {
|
395 |
|
396 | return;
|
397 | }
|
398 | if (message.indexOf("Skipping static resource") === 0) {
|
399 | return;
|
400 | }
|
401 | console.log(message);
|
402 | },
|
403 | minify: true,
|
404 | navigateFallback: publicUrl + "/index.html",
|
405 | navigateFallbackWhitelist: [/^(?!\/__).*/],
|
406 | staticFileGlobsIgnorePatterns: [/\.map$/, /asset-manifest\.json$/]
|
407 | }),
|
408 | new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/)
|
409 | ]
|
410 | .concat(moredPlugins),
|
411 | node: {
|
412 | dgram: "empty",
|
413 | fs: "empty",
|
414 | net: "empty",
|
415 | tls: "empty",
|
416 | child_process: "empty"
|
417 | }
|
418 | };
|