config-builder.js 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. 'use strict';
  2. const path = require('path'),
  3. webpack = require('webpack'),
  4. HtmlWebpackPlugin = require('html-webpack-plugin'),
  5. MiniCssExtractPlugin = require("mini-css-extract-plugin");
  6. const PROJECT_ROOT = path.resolve(__dirname, "..");
  7. module.exports = (env) => {
  8. const isDev = env === 'development';
  9. const isTest = env === 'test';
  10. const isProd = !isDev && !isTest;
  11. const getAppEntry = () => {
  12. const appEntry = path.resolve(PROJECT_ROOT, "src/app/entry.jsx");
  13. if(isDev) {
  14. return [
  15. 'react-hot-loader/patch',
  16. 'webpack-dev-server/client?http://localhost:9000',
  17. 'webpack/hot/only-dev-server',
  18. appEntry
  19. ]
  20. } else {
  21. return [appEntry]
  22. }
  23. };
  24. const getPlugins = () => {
  25. // common plugins
  26. let plugins = [
  27. // Global variables
  28. new webpack.DefinePlugin({
  29. 'process.env.NODE_ENV': JSON.stringify(env),
  30. '__DEV__': isDev,
  31. '__PROD__': isProd,
  32. '__TEST__': isTest,
  33. }),
  34. // ignore moment locale files
  35. new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
  36. // extract styles to css file
  37. new MiniCssExtractPlugin({
  38. filename: "[name].[contenthash].css",
  39. chunkFilename: "[id].css",
  40. disable: isDev,
  41. }),
  42. // makes index.html
  43. new HtmlWebpackPlugin({
  44. template: path.resolve(PROJECT_ROOT, 'src/index.ejs'),
  45. })
  46. ];
  47. // development plugins
  48. if(isDev) {
  49. plugins.push(
  50. // Hot Reload (HMR)
  51. new webpack.HotModuleReplacementPlugin(),
  52. // Named Modules
  53. new webpack.NamedModulesPlugin()
  54. );
  55. }
  56. // production plugins
  57. if(isProd) {
  58. plugins.push(
  59. new webpack.optimize.ModuleConcatenationPlugin()
  60. );
  61. }
  62. return plugins;
  63. };
  64. return {
  65. target: 'web',
  66. mode: isProd ? "production" : "development",
  67. context: PROJECT_ROOT,
  68. entry: {
  69. app: getAppEntry()
  70. },
  71. output: {
  72. path: path.resolve(PROJECT_ROOT, isProd ? 'dist' : 'build'),
  73. filename: isProd ? '[name].[chunkhash:8].js' : '[name].js',
  74. publicPath: '/',
  75. sourceMapFilename: '[file].map',
  76. chunkFilename: isProd ? '[name].[chunkhash:8].js' : '[name].js',
  77. pathinfo: isDev
  78. },
  79. devtool: isProd ? "hidden-sourcemap" : 'eval',
  80. resolve: {
  81. extensions: ['.js', '.jsx', '.ts', '.tsx'],
  82. modules: ["node_modules", "src"],
  83. alias: {}
  84. },
  85. module: {
  86. rules: [
  87. // JS / JSX files
  88. {
  89. test: /\.(js|jsx)$/,
  90. exclude: /(node_modules)/,
  91. use: [
  92. {
  93. loader: 'babel-loader',
  94. options: {
  95. cacheDirectory: true
  96. }
  97. }
  98. ]
  99. },
  100. // SASS files
  101. {
  102. test: /\.scss$/,
  103. exclude: /(node_modules|bower_components)/,
  104. use: [
  105. isDev ? "style-loader" : MiniCssExtractPlugin.loader,
  106. {
  107. loader: "css-loader",
  108. options: {
  109. importLoaders: 2,
  110. url: true,
  111. import: false,
  112. sourceMap: isDev
  113. }
  114. },
  115. {
  116. loader: "postcss-loader",
  117. options: {
  118. sourceMap: isDev,
  119. plugins: isDev ? [] : [
  120. require("autoprefixer"),
  121. require("cssnano")({
  122. safe: true,
  123. zindex: false,
  124. discardComments: {
  125. removeAll: true
  126. }
  127. })
  128. ]
  129. }
  130. },
  131. {
  132. loader: "sass-loader",
  133. options: {
  134. sourceMap: isDev,
  135. includePaths: [".", path.join(process.cwd(), "src/app/core/styles")]
  136. }
  137. }
  138. ]
  139. },
  140. // Plain CSS files
  141. {
  142. test: /\.css$/,
  143. use: [
  144. isDev ? "style-loader" : MiniCssExtractPlugin.loader,
  145. {
  146. loader: "css-loader",
  147. options: {
  148. importLoaders: 1,
  149. url: true,
  150. import: false,
  151. sourceMap: isDev
  152. }
  153. },
  154. {
  155. loader: "postcss-loader",
  156. options: {
  157. sourceMap: isDev,
  158. plugins: isDev ? [] : [
  159. require("autoprefixer"),
  160. require("cssnano")({
  161. safe: true,
  162. zindex: false,
  163. discardComments: {
  164. removeAll: true
  165. }
  166. })
  167. ]
  168. }
  169. }
  170. ]
  171. },
  172. // images loader
  173. {
  174. test: /\.(png|jpe?g|gif|svg|ico)(\?.*)?$/,
  175. use: [
  176. {
  177. loader: 'file-loader',
  178. options: {
  179. name: "[name].[ext]",
  180. outputPath: isProd ? "../images/" : "images/"
  181. }
  182. }
  183. ]
  184. },
  185. // font loader
  186. {
  187. test: /\.(woff|woff2|ttf|eot)(\?.*)?$/,
  188. use: [
  189. {
  190. loader: 'file-loader',
  191. options: {
  192. name: "[name].[ext]",
  193. publicPath: isProd ? "" : "/webpack/",
  194. useRelativePath: isProd,
  195. outputPath: isProd ? "../fonts/" : "fonts/"
  196. }
  197. }
  198. ]
  199. }
  200. ]
  201. },
  202. plugins: getPlugins(),
  203. node: {
  204. __filename: true,
  205. __dirname: true,
  206. fs: 'empty',
  207. vm: 'empty',
  208. net: 'empty',
  209. tls: 'empty',
  210. }
  211. };
  212. };