1 | const path = require('path');
|
2 | const webpack = require('webpack');
|
3 | const BabelConfig = require('./BabelConfig');
|
4 | const Utils = require('../lib/utils');
|
5 | const ProgressBarPlugin = require('progress-bar-webpack-plugin');
|
6 | const ExtractTextPlugin = require('extract-text-webpack-plugin');
|
7 | const HtmlWebpackPlugin = require('html-webpack-plugin');
|
8 | const nodeExternals = require('webpack-node-externals');
|
9 | const CleanWebpackPlugin = require('clean-webpack-plugin');
|
10 | const LessPluginCleanCSS = require('less-plugin-clean-css');
|
11 |
|
12 | exports._default = function (env) {
|
13 | env = env || 'development'
|
14 | const output = {
|
15 | path: path.join(process.cwd(), `.${path.sep}dist${path.sep}`),
|
16 | };
|
17 |
|
18 | const AUTOPREFIXER_BROWSERS = [
|
19 | 'Android 2.3',
|
20 | 'Android >= 4',
|
21 | 'Chrome >= 35',
|
22 | 'Firefox >= 31',
|
23 | 'Explorer >= 8',
|
24 | 'iOS >= 6',
|
25 | 'Opera >= 12',
|
26 | 'Safari >= 7.1',
|
27 | ];
|
28 |
|
29 | const GLOBALS = {
|
30 | __IS_SSR__: false,
|
31 | __MODE__:`'${env}'`,
|
32 | 'process.env.NODE_ENV': `'${env}'`,
|
33 | };
|
34 |
|
35 | const plugins = [
|
36 | new webpack.DefinePlugin(GLOBALS),
|
37 | new webpack.optimize.AggressiveMergingPlugin(),
|
38 | new webpack.NoEmitOnErrorsPlugin(),
|
39 | new webpack.optimize.ModuleConcatenationPlugin(),
|
40 | new ProgressBarPlugin(),
|
41 | new webpack.ProvidePlugin({
|
42 | React: 'react',
|
43 | ReactDOM: 'react-dom',
|
44 | }),
|
45 | new webpack.optimize.UglifyJsPlugin({
|
46 | sourceMap:env === 'development',
|
47 | beautify: false,
|
48 | comments: false,
|
49 | compress: {
|
50 | warnings: false,
|
51 | drop_console: false,
|
52 | collapse_vars: true,
|
53 | reduce_vars: true,
|
54 | }
|
55 | }),
|
56 | ];
|
57 |
|
58 | const moduleConfig = {
|
59 | rules: [{
|
60 | enforce: 'pre',
|
61 | test: /\.jsx?$/,
|
62 | use: {
|
63 | loader: require.resolve('babel-loader'),
|
64 | options: BabelConfig.get(),
|
65 | },
|
66 | include: /(node_modules\/igame_base_libs|src)/
|
67 | }, {
|
68 | test: /\.(png|jpg|jpeg|gif)$/,
|
69 | use: require.resolve('url-loader') + '?limit=1024&&name=images/[name].[hash:6].[ext]',
|
70 | }, {
|
71 | test: /\.(eot|ttf|wav|mp3|svg|woff|woff2)$/,
|
72 | use: require.resolve('file-loader') + '?name=fonts/[name].[hash:6].[ext]',
|
73 | }, {
|
74 | test: /\.css$/,
|
75 | use: ExtractTextPlugin.extract({
|
76 | allChunks: true,
|
77 | fallback: require.resolve('style-loader'),
|
78 | use: [require.resolve('css-loader'), {
|
79 | loader: require.resolve('postcss-loader'),
|
80 | options: {
|
81 | plugins: (loader) => [
|
82 | require('postcss-import')({
|
83 | path: [Utils.resolveNodeModulesPath()]
|
84 | }),
|
85 | require('postcss-mixins')(),
|
86 | require('postcss-nested')(),
|
87 | require('cssnano')({
|
88 | colormin: false,
|
89 | zindex: false,
|
90 | autoprefixer: false,
|
91 | }),
|
92 | require('postcss-cssnext')({
|
93 | browsers: AUTOPREFIXER_BROWSERS,
|
94 | }),
|
95 | require('postcss-opacity')(),
|
96 | require('../postcssPlugins/rgbaPlugin')(),
|
97 | ]
|
98 | }
|
99 | }]
|
100 | })
|
101 | },{
|
102 | test: /\.less$/,
|
103 | use: ExtractTextPlugin.extract({
|
104 | allChunks: true,
|
105 | fallback: require.resolve('style-loader'),
|
106 | use:[require.resolve('css-loader'),{
|
107 | loader:require.resolve('less-loader'),
|
108 | options:{
|
109 | plugins:[
|
110 | new LessPluginCleanCSS({ advanced: true })
|
111 | ]
|
112 | }
|
113 | }]
|
114 | })
|
115 | }]
|
116 | };
|
117 |
|
118 | const resolve = {
|
119 | extensions: ['.webpack.js', '.web.js', '.js', '.jsx'],
|
120 | modules: [
|
121 | Utils.resolveNodeModulesPath(),
|
122 | 'node_modules'
|
123 | ]
|
124 | };
|
125 |
|
126 | const config = {
|
127 | entry: {},
|
128 | output,
|
129 | module: moduleConfig,
|
130 | plugins,
|
131 | externals: {
|
132 | 'react': {
|
133 | commonjs: 'react',
|
134 | commonjs2: 'react',
|
135 | amd: 'react',
|
136 | root: 'React',
|
137 | 'var': 'React'
|
138 | },
|
139 | 'react-dom': {
|
140 | commonjs: 'react-dom',
|
141 | commonjs2: 'react-dom',
|
142 | amd: 'react-dom',
|
143 | root: 'ReactDOM',
|
144 | 'var': 'ReactDOM'
|
145 | },
|
146 | 'react-router': {
|
147 | commonjs: 'react-router',
|
148 | commonjs2: 'react-router',
|
149 | amd: 'react-router',
|
150 | root: 'ReactRouter',
|
151 | 'var': 'ReactRouter'
|
152 | },
|
153 | },
|
154 | resolve,
|
155 | };
|
156 |
|
157 | return config;
|
158 | }
|
159 |
|
160 | exports.development = function () {
|
161 | var config = this._default();
|
162 | return config
|
163 | }
|
164 |
|
165 | exports.postDevelopment = function (config, devServerConfig,webpackConfig) {
|
166 | process.noDeprecation = true;
|
167 | var nodeModulesPath = Utils.resolveNodeModulesPath();
|
168 | var preEntrys = [];
|
169 | config.output.publicPath = webpackConfig.devPath;
|
170 |
|
171 | config.output.filename = '[name].js';
|
172 | if(webpackConfig.preset === 'ie8'){
|
173 | shimIe8Plugins(config);
|
174 | }
|
175 | config.plugins.push(new ExtractTextPlugin('[name].css'));
|
176 | if (devServerConfig.hot) {
|
177 | const patch = path.join(nodeModulesPath,`react-hot-loader${path.sep}patch`);
|
178 | let devServer = path.join(nodeModulesPath,`webpack-dev-server${path.sep}client`);
|
179 | devServer = `${devServer}?http://127.0.0.1:${devServerConfig.port}/`;
|
180 | const hotDevServer = path.join(nodeModulesPath,`webpack${path.sep}hot${path.sep}dev-server`);
|
181 | preEntrys = preEntrys.concat([patch, devServer, hotDevServer])
|
182 | }
|
183 |
|
184 | if(webpackConfig.devBuildOnly && Array.isArray(webpackConfig.devBuildOnly) && webpackConfig.devBuildOnly.length > 0){
|
185 | const obj = {};
|
186 | webpackConfig.devBuildOnly.map((item)=>{
|
187 | obj[item] = config.entry[item];
|
188 | })
|
189 | config.entry = obj;
|
190 | }
|
191 |
|
192 | Object.keys(config.entry).forEach(function (entry) {
|
193 | if (Array.isArray(config.entry[entry])) {
|
194 | config.entry[entry].unshift.apply(config.entry[entry], preEntrys)
|
195 | } else {
|
196 | config.entry[entry] = preEntrys.concat(config.entry[entry])
|
197 | }
|
198 |
|
199 | config.plugins.push(new HtmlWebpackPlugin({
|
200 | template: path.join(__dirname, `..${path.sep}template${path.sep}js.ejs`),
|
201 | filename: process.cwd() + `${path.sep}dist_ejs${path.sep}${entry}.js.ejs`,
|
202 | chunks: [entry],
|
203 | inject:false
|
204 | }))
|
205 | config.plugins.push(new HtmlWebpackPlugin({
|
206 | template: path.join(__dirname, `..${path.sep}template${path.sep}css.ejs`),
|
207 | filename:process.cwd() + `${path.sep}dist_ejs${path.sep}${entry}.css.ejs`,
|
208 | chunks: [entry],
|
209 | favicon:webpackConfig.favicon,
|
210 | inject:false
|
211 | }))
|
212 | })
|
213 | if (devServerConfig.hot) {
|
214 | config.module.rules.unshift({
|
215 | test: /\.jsx?$/,
|
216 | use: require.resolve(`react-hot-loader${path.sep}webpack`),
|
217 | exclude: /node_modules/,
|
218 | })
|
219 | config.plugins.push(new webpack.HotModuleReplacementPlugin());
|
220 | }
|
221 | config.devtool = webpackConfig.sourceMap || '';
|
222 | }
|
223 |
|
224 | exports.production = function () {
|
225 | var config = this._default('production')
|
226 | return config
|
227 | }
|
228 |
|
229 | exports.postProduction = function (config, devServerConfig,webpackConfig) {
|
230 | var preEntrys = [];
|
231 | config.output.publicPath = process.env.NODE_ENV === "production" ? webpackConfig.cdnPath : webpackConfig.fatPath;
|
232 |
|
233 | config.output.filename = webpackConfig.libs ? '[name].js' : '[name].[chunkhash:6].js'
|
234 | if(webpackConfig.preset === 'ie8'){
|
235 | shimIe8Plugins(config);
|
236 | }
|
237 | config.plugins.unshift(new CleanWebpackPlugin(['dist'], {
|
238 | root: process.cwd(),
|
239 | verbose: true,
|
240 | allowExternal: true
|
241 | }));
|
242 | webpackConfig.libs ? config.plugins.push(new ExtractTextPlugin('[name].css')) : config.plugins.push(new ExtractTextPlugin('[name].[contenthash:6].css'));
|
243 | let tempPath = '';
|
244 | webpackConfig.useTempPath && process.env.NODE_ENV === "production" ? tempPath = 'dist_ejs_temp' : tempPath = 'dist_ejs';
|
245 | Object.keys(config.entry).forEach(function (entry) {
|
246 | if (Array.isArray(config.entry[entry])) {
|
247 | config.entry[entry].unshift.apply(config.entry[entry], preEntrys)
|
248 | } else {
|
249 | config.entry[entry] = preEntrys.concat(config.entry[entry])
|
250 | }
|
251 | if(!webpackConfig.libs){
|
252 | config.plugins.push(new HtmlWebpackPlugin({
|
253 | template: path.join(__dirname, `..${path.sep}template${path.sep}css.ejs`),
|
254 | filename: process.cwd() + `${path.sep}${tempPath}${path.sep}${entry}.css.ejs`,
|
255 | chunks: [entry],
|
256 | favicon:webpackConfig.favicon,
|
257 | inject:false
|
258 | }))
|
259 | config.plugins.push(new HtmlWebpackPlugin({
|
260 | template: path.join(__dirname, `..${path.sep}template${path.sep}js.ejs`),
|
261 | filename: process.cwd() + `${path.sep}${tempPath}${path.sep}${entry}.js.ejs`,
|
262 | chunks: [entry],
|
263 | inject:false
|
264 | }))
|
265 | }
|
266 | });
|
267 | }
|
268 |
|
269 |
|
270 | exports.NodeSSR = function () {
|
271 | var config = this._default('NodeSSR')
|
272 | return config;
|
273 | }
|
274 |
|
275 | exports.postNodeSSR = function (config, devServerConfig,webpackConfig) {
|
276 | var serverConfig = this._default('NodeSSR');
|
277 | let preEntrys = [];
|
278 | let nodeServerEntry = webpackConfig.nodeServerEntry;
|
279 | Object.keys(nodeServerEntry).forEach(function (entry) {
|
280 | if (Array.isArray(nodeServerEntry[entry])) {
|
281 | nodeServerEntry[entry].unshift.apply(nodeServerEntry[entry], preEntrys)
|
282 | } else {
|
283 | nodeServerEntry[entry] = preEntrys.concat(nodeServerEntry[entry])
|
284 | }
|
285 | });
|
286 | Object.assign(serverConfig, {
|
287 | entry : nodeServerEntry,
|
288 | output: {
|
289 | path: path.join(process.cwd(), `.${path.sep}dist_server${path.sep}`),
|
290 | filename: "[name].server.js",
|
291 | libraryTarget: 'commonjs2',
|
292 | publicPath:process.env.NODE_ENV === "production" ? webpackConfig.cdnPath : process.env.NODE_ENV === "fat" ? webpackConfig.fatPath : webpackConfig.devPath,
|
293 | },
|
294 | module: {
|
295 | rules: [{
|
296 | test: /\.jsx?$/,
|
297 | use: {
|
298 | loader: require.resolve('babel-loader'),
|
299 | options:{
|
300 | presets: ['react'],
|
301 | plugins: [
|
302 | require.resolve("babel-plugin-transform-decorators-legacy"),
|
303 | require.resolve("babel-plugin-transform-es2015-modules-commonjs"),
|
304 | ]
|
305 | }
|
306 | },
|
307 | include: /(node_modules\/igame_base_libs|src)/
|
308 | },
|
309 | {
|
310 | test: /\.(png|jpg|jpeg|gif)$/,
|
311 | use: require.resolve('url-loader'),
|
312 | },
|
313 | {
|
314 | test: /\.(styl|css)$/,
|
315 | use: 'null-loader'
|
316 | },
|
317 | ]
|
318 | },
|
319 | plugins: [
|
320 | new webpack.ProvidePlugin({
|
321 | React: 'react',
|
322 | ReactDOM: 'react-dom',
|
323 | }),
|
324 | new webpack.DefinePlugin({
|
325 | __IS_SSR__: true,
|
326 | __MODE__:'"node_ssr"'
|
327 | }),
|
328 | ],
|
329 | externals: [nodeExternals({
|
330 | whitelist: ['igame_base_libs']
|
331 | })]
|
332 | });
|
333 | return serverConfig;
|
334 | }
|
335 |
|
336 | function shimIe8Plugins(config) {
|
337 | config.module.rules.unshift({
|
338 | enforce: 'post',
|
339 | test: /\.js$/,
|
340 | use: {
|
341 | loader: require.resolve('es3ify-loader'),
|
342 | },
|
343 | include: /(node_modules\/igame_base_libs|src)/
|
344 | });
|
345 | config.plugins.pop();
|
346 | config.plugins.push(new webpack.optimize.UglifyJsPlugin({
|
347 | compress: {
|
348 | unused: true,
|
349 | drop_console: false,
|
350 | drop_debugger: true,
|
351 | dead_code: true,
|
352 | properties: false,
|
353 | warnings: false,
|
354 | screw_ie8: false,
|
355 | },
|
356 | mangle: false,
|
357 | mangle: {
|
358 | screw_ie8: false
|
359 | },
|
360 | output: {
|
361 | screw_ie8: false
|
362 | },
|
363 | comments: false
|
364 | }))
|
365 | }
|