UNPKG

12.8 kBJavaScriptView Raw
1/*
2 * @Author: Eward
3 * @Date: 2017-08-17 21:30:40
4 * @Last Modified by: Eward
5 * @Last Modified time: 2017-10-27 15:22:24
6 */
7"use strict";
8
9const fs = require("fs"); //eward
10const autoprefixer = require("autoprefixer");
11const path = require("path");
12const webpack = require("webpack");
13const HtmlWebpackPlugin = require("html-webpack-plugin");
14const ExtractTextPlugin = require("extract-text-webpack-plugin");
15const ManifestPlugin = require("webpack-manifest-plugin");
16const InterpolateHtmlPlugin = require("react-dev-utils/InterpolateHtmlPlugin");
17const SWPrecacheWebpackPlugin = require("sw-precache-webpack-plugin");
18const eslintFormatter = require("react-dev-utils/eslintFormatter");
19const ModuleScopePlugin = require("react-dev-utils/ModuleScopePlugin");
20const paths = require("./paths");
21const getClientEnvironment = require("./env");
22const os = require("os");
23const HappyPack = require("happypack");
24const happyThreadPool = HappyPack.ThreadPool({ size: os.cpus().length });
25const AutoDllPlugin = require("autodll-webpack-plugin");
26const ParallelUglifyPlugin = require("webpack-parallel-uglify-plugin");
27
28const publicPath = paths.servedPath;
29const shouldUseRelativeAssetPaths = publicPath === "./";
30const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== "false";
31const publicUrl = publicPath.slice(0, -1);
32const env = getClientEnvironment(publicUrl);
33
34if (env.stringified["process.env"].NODE_ENV !== '"production"') {
35 throw new Error("Production builds must have NODE_ENV=production.");
36}
37
38const cssFilename = "static/css/[name].[contenthash:8].css";
39
40const extractTextPluginOptions = shouldUseRelativeAssetPaths
41 ? // Making sure that the publicPath goes back to to build folder.
42 { publicPath: Array(cssFilename.split("/").length).join("../") }
43 : {};
44
45const alias =
46 (fs.existsSync(paths.appConfig) && require(paths.appConfig).alias) || {};
47
48for (let i in alias) {
49 alias[i] = paths.appSrc + alias[i];
50}
51
52/** ---- ---- by Eward */
53const modifyVars =
54 (fs.existsSync(paths.appConfig) && require(paths.appConfig).modifyVars) || {};
55const moreLoaders =
56 (fs.existsSync(paths.appConfig) && require(paths.appConfig).loaders) || [];
57const moredPlugins =
58 (fs.existsSync(paths.appConfig) && require(paths.appConfig).prodPlugins) ||
59 [];
60const tempVendors = require(paths.appConfig).vendors || [];
61
62let vendors = {
63 vendors: []
64};
65if (Array.isArray(tempVendors)) {
66 vendors = {
67 vendors: tempVendors
68 };
69}
70if (tempVendors.toString() === "[object Object]") {
71 vendors = tempVendors;
72}
73/** ---- ---- by Eward */
74
75module.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 //eward
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" // React doesn't support IE8 anyway
188 ],
189 flexbox: "no-2009"
190 })
191 ]
192 }
193 }
194 ]
195 },
196 extractTextPluginOptions
197 )
198 )
199 },
200 //新增对module less的支持
201 {
202 //eward
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" // React doesn't support IE8 anyway
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 //新增对less的支持
250 {
251 //eward
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" // React doesn't support IE8 anyway
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) //eward
304 }
305 ]
306 },
307 plugins: [
308 //增加happypack进行多进程打包
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, // will inject the DLL bundle to index.html
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 // 删除所有的 `console` 语句
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 // 删除所有的 `console` 语句
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 // This message occurs for every build and is a bit too noisy.
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 ] //eward
410 .concat(moredPlugins),
411 node: {
412 dgram: "empty",
413 fs: "empty",
414 net: "empty",
415 tls: "empty",
416 child_process: "empty"
417 }
418};