1 | 'use strict';
|
2 |
|
3 |
|
4 |
|
5 | const path = require('path');
|
6 | const webpack = require('webpack');
|
7 | const HtmlWebpackPlugin = require('html-webpack-plugin');
|
8 | const ManifestPlugin = require('webpack-manifest-plugin');
|
9 | const ChunkManifestPlugin = require('chunk-manifest-webpack-plugin');
|
10 | const WebpackMd5Hash = require('webpack-md5-hash');
|
11 | const WebpackCleanupPlugin = require('webpack-cleanup-plugin');
|
12 | const merge = require('webpack-merge');
|
13 | const prettyjson = require('prettyjson');
|
14 | const semverUtils = require('semver-utils');
|
15 | const webpackVersion = semverUtils.parseRange(require('webpack/package.json').version)[0].major;
|
16 | const isWebpack2 = webpackVersion === '2';
|
17 | const nodeModulesDir = path.resolve(__dirname, '../node_modules');
|
18 |
|
19 |
|
20 | const ExtractTextPlugin = require("extract-text-webpack-plugin");
|
21 | const autoprefixer = require('autoprefixer');
|
22 |
|
23 | function validateWebpackConfig(webpackConfig) {
|
24 | webpackConfig.module.loaders.forEach(loader => {
|
25 | if (!loader.include && !loader.exclude) {
|
26 | throw Error('DvhbWebpack: "include" option is missing for ' + loader.test + ' Webpack loader.');
|
27 | }
|
28 | });
|
29 | }
|
30 |
|
31 | module.exports = function (config, env) {
|
32 | process.env.NODE_ENV = process.env.BABEL_ENV = env;
|
33 |
|
34 | const isProd = env === 'production';
|
35 |
|
36 | let webpackConfig = {
|
37 | output: {
|
38 | path: config.distDir,
|
39 | filename: '[name].js'
|
40 | },
|
41 | resolveLoader: {
|
42 | moduleExtensions: ['-loader', '.loader'],
|
43 | },
|
44 | plugins: [
|
45 | new webpack.DefinePlugin({
|
46 | 'process.env': {
|
47 | NODE_ENV: JSON.stringify(env),
|
48 | },
|
49 | }),
|
50 | new webpack.optimize.CommonsChunkPlugin({
|
51 | name: 'vendor',
|
52 | minChunks: function (module) {
|
53 | return /node_modules/.test(module.resource);
|
54 | }
|
55 | }),
|
56 | new WebpackMd5Hash(),
|
57 | new ManifestPlugin(),
|
58 | new ChunkManifestPlugin({
|
59 | filename: "chunk-manifest.json",
|
60 | manifestVariable: "webpackManifest"
|
61 | }),
|
62 | ],
|
63 | module: {
|
64 | loaders: [],
|
65 | },
|
66 | postcss: [
|
67 | autoprefixer({
|
68 | browsers: ['last 6 versions']
|
69 | })
|
70 | ],
|
71 | };
|
72 |
|
73 | if (config.template) {
|
74 | webpackConfig.plugins.push(
|
75 | new HtmlWebpackPlugin({
|
76 | title: config.title,
|
77 | template: config.template,
|
78 | inject: true,
|
79 | }));
|
80 | }
|
81 |
|
82 | const loaderModulesDirectories = [
|
83 | nodeModulesDir,
|
84 | 'node_modules',
|
85 | ];
|
86 |
|
87 | if (isWebpack2) {
|
88 | webpackConfig = merge(webpackConfig, {
|
89 | resolve: {
|
90 | extensions: ['.js', '.jsx', '.json'],
|
91 | modules: [
|
92 | config.sourceDir,
|
93 | nodeModulesDir,
|
94 | 'node_modules',
|
95 | ],
|
96 | },
|
97 | resolveLoader: {
|
98 | modules: loaderModulesDirectories,
|
99 | },
|
100 | plugins: [
|
101 | new webpack.LoaderOptionsPlugin({
|
102 | minimize: isProd,
|
103 | debug: !isProd
|
104 | }),
|
105 | ],
|
106 | });
|
107 | }
|
108 | else {
|
109 | webpackConfig = merge(webpackConfig, {
|
110 | resolve: {
|
111 | extensions: ['', '.js', '.jsx', '.json'],
|
112 | root: config.sourceDir,
|
113 | moduleDirectories: [
|
114 | nodeModulesDir,
|
115 | 'node_modules',
|
116 | ],
|
117 | },
|
118 | resolveLoader: {
|
119 | modulesDirectories: loaderModulesDirectories,
|
120 | },
|
121 | debug: !isProd,
|
122 | });
|
123 | }
|
124 |
|
125 | const entryScript = path.resolve(config.sourceDir, 'index');
|
126 |
|
127 | if (isProd) {
|
128 | webpackConfig = merge(webpackConfig, {
|
129 | output: {
|
130 | filename: '[name].[chunkhash].js',
|
131 | chunkFilename: '[name].[chunkhash].js'
|
132 | },
|
133 | entry: [
|
134 | entryScript,
|
135 | ],
|
136 | devtool: false,
|
137 | cache: false,
|
138 | plugins: [
|
139 | new WebpackCleanupPlugin({
|
140 | quiet: true,
|
141 | }),
|
142 | new webpack.optimize.DedupePlugin(),
|
143 | new webpack.optimize.UglifyJsPlugin({
|
144 | compress: {
|
145 | warnings: false,
|
146 | },
|
147 | output: {
|
148 | comments: false,
|
149 | },
|
150 | mangle: false,
|
151 | }),
|
152 | new ExtractTextPlugin('[name].[contenthash].css')
|
153 | ],
|
154 | module: {
|
155 | loaders: [
|
156 | {
|
157 | test: /\.css$/,
|
158 | include: config.sourceDir,
|
159 | loader: ExtractTextPlugin.extract("style", "raw!csso?-restructure!postcss")
|
160 | },
|
161 | {
|
162 | test: /\.styl$/,
|
163 | include: config.sourceDir,
|
164 | loader: ExtractTextPlugin.extract("style", "raw!csso?-restructure!postcss!stylus")
|
165 | },
|
166 | ],
|
167 | },
|
168 | });
|
169 | }
|
170 | else {
|
171 | webpackConfig = merge(webpackConfig, {
|
172 | entry: [
|
173 | 'webpack-hot-middleware/client?reload=true',
|
174 | entryScript,
|
175 | ],
|
176 | cache: true,
|
177 | devtool: 'eval',
|
178 | stats: {
|
179 | colors: true,
|
180 | reasons: true,
|
181 | },
|
182 | plugins: [
|
183 | new webpack.optimize.OccurenceOrderPlugin(),
|
184 | new webpack.HotModuleReplacementPlugin(),
|
185 | new webpack.NoErrorsPlugin(),
|
186 | ],
|
187 | module: {
|
188 | loaders: [
|
189 | {
|
190 | test: /\.styl$/,
|
191 | include: config.sourceDir,
|
192 | loader: 'style!raw!postcss!stylus'
|
193 | },
|
194 | {
|
195 | test: /\.css$/,
|
196 | include: config.sourceDir,
|
197 | loader: 'style!raw'
|
198 | }
|
199 | ],
|
200 | },
|
201 | });
|
202 | }
|
203 |
|
204 | if (config.extendWebpackConfig) {
|
205 | webpackConfig = config.extendWebpackConfig(webpackConfig, env);
|
206 | validateWebpackConfig(webpackConfig);
|
207 | }
|
208 |
|
209 | if (config.verbose) {
|
210 | console.log();
|
211 | console.log('Using Webpack config:');
|
212 | console.log(prettyjson.render(webpackConfig));
|
213 | console.log();
|
214 | }
|
215 |
|
216 | return webpackConfig;
|
217 | };
|