You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

239 lines
5.5 KiB

  1. const webpack = require('webpack')
  2. const path = require('path')
  3. const fs = require('fs-extra')
  4. const { VueLoaderPlugin } = require('vue-loader')
  5. const CopyWebpackPlugin = require('copy-webpack-plugin')
  6. const HtmlWebpackPlugin = require('html-webpack-plugin')
  7. const HtmlWebpackPugPlugin = require('html-webpack-pug-plugin')
  8. const SimpleProgressWebpackPlugin = require('simple-progress-webpack-plugin')
  9. const WriteFilePlugin = require('write-file-webpack-plugin')
  10. const babelConfig = fs.readJsonSync(path.join(process.cwd(), '.babelrc'))
  11. const cacheDir = '.webpack-cache/cache'
  12. const babelDir = path.join(process.cwd(), '.webpack-cache/babel')
  13. process.noDeprecation = true
  14. module.exports = {
  15. mode: 'development',
  16. entry: {
  17. client: ['./client/index.js', 'webpack-hot-middleware/client']
  18. },
  19. output: {
  20. path: path.join(process.cwd(), 'assets'),
  21. publicPath: '/',
  22. filename: 'js/[name].js',
  23. chunkFilename: 'js/[name].js',
  24. globalObject: 'this',
  25. pathinfo: true
  26. },
  27. module: {
  28. rules: [
  29. {
  30. test: /\.js$/,
  31. exclude: /node_modules/,
  32. use: [
  33. {
  34. loader: 'cache-loader',
  35. options: {
  36. cacheDirectory: cacheDir
  37. }
  38. },
  39. {
  40. loader: 'babel-loader',
  41. options: {
  42. ...babelConfig,
  43. cacheDirectory: babelDir
  44. }
  45. }
  46. ]
  47. },
  48. {
  49. test: /\.css$/,
  50. use: [
  51. 'style-loader',
  52. 'css-loader',
  53. 'postcss-loader'
  54. ]
  55. },
  56. {
  57. test: /\.scss$/,
  58. use: [
  59. {
  60. loader: 'cache-loader',
  61. options: {
  62. cacheDirectory: cacheDir
  63. }
  64. },
  65. 'style-loader',
  66. 'css-loader',
  67. 'postcss-loader',
  68. {
  69. loader: 'sass-loader',
  70. options: {
  71. sourceMap: false
  72. }
  73. },
  74. {
  75. loader: 'sass-resources-loader',
  76. options: {
  77. resources: path.join(process.cwd(), '/client/scss/global.scss')
  78. }
  79. }
  80. ]
  81. },
  82. {
  83. test: /\.styl$/,
  84. use: [
  85. 'style-loader',
  86. 'css-loader',
  87. 'postcss-loader',
  88. 'stylus-loader'
  89. ]
  90. },
  91. {
  92. test: /\.vue$/,
  93. loader: 'vue-loader'
  94. },
  95. {
  96. test: /\.pug$/,
  97. exclude: [
  98. path.join(process.cwd(), 'dev')
  99. ],
  100. loader: 'pug-plain-loader'
  101. },
  102. {
  103. test: /\.(png|jpg|gif)$/,
  104. use: [
  105. {
  106. loader: 'url-loader',
  107. options: {
  108. limit: 8192
  109. }
  110. }
  111. ]
  112. },
  113. {
  114. test: /\.svg$/,
  115. exclude: [
  116. path.join(process.cwd(), 'client/svg')
  117. ],
  118. use: [
  119. {
  120. loader: 'file-loader',
  121. options: {
  122. name: '[name].[ext]',
  123. outputPath: 'svg/'
  124. }
  125. }
  126. ]
  127. },
  128. {
  129. test: /\.svg$/,
  130. include: [
  131. path.join(process.cwd(), 'client/svg')
  132. ],
  133. use: [
  134. {
  135. loader: 'raw-loader'
  136. }
  137. ]
  138. },
  139. {
  140. test: /\.(graphql|gql)$/,
  141. exclude: /node_modules/,
  142. loader: 'graphql-tag/loader'
  143. },
  144. {
  145. test: /.jsx$/,
  146. loader: 'babel-loader',
  147. exclude: /node_modules/,
  148. options: {
  149. presets: ['es2015', 'react']
  150. }
  151. },
  152. {
  153. test: /\.flow$/,
  154. loader: 'ignore-loader'
  155. }
  156. ]
  157. },
  158. plugins: [
  159. new VueLoaderPlugin(),
  160. new CopyWebpackPlugin([
  161. { from: 'client/static' },
  162. { from: './node_modules/graphql-voyager/dist/voyager.worker.js', to: 'js/' }
  163. ], {}),
  164. new HtmlWebpackPlugin({
  165. template: 'dev/templates/master.pug',
  166. filename: '../server/views/master.pug',
  167. hash: false,
  168. inject: 'head'
  169. }),
  170. new HtmlWebpackPugPlugin(),
  171. new SimpleProgressWebpackPlugin({
  172. format: 'compact'
  173. }),
  174. new webpack.DefinePlugin({
  175. 'process.env': { NODE_ENV: '"development"' },
  176. '__REACT_DEVTOOLS_GLOBAL_HOOK__': '({ isDisabled: true })'
  177. }),
  178. new WriteFilePlugin(),
  179. new webpack.HotModuleReplacementPlugin(),
  180. new webpack.WatchIgnorePlugin([
  181. /node_modules/
  182. ])
  183. ],
  184. optimization: {
  185. namedModules: true,
  186. namedChunks: true,
  187. splitChunks: {
  188. cacheGroups: {
  189. default: {
  190. minChunks: 2,
  191. priority: -20,
  192. reuseExistingChunk: true
  193. },
  194. vendor: {
  195. test: /[\\/]node_modules[\\/]/,
  196. minChunks: 2,
  197. priority: -10
  198. }
  199. }
  200. },
  201. runtimeChunk: 'single'
  202. },
  203. resolve: {
  204. mainFields: ['browser', 'main', 'module'],
  205. symlinks: true,
  206. alias: {
  207. '@': path.join(process.cwd(), 'client'),
  208. 'vue$': 'vue/dist/vue.esm.js',
  209. 'gql': path.join(process.cwd(), 'client/graph'),
  210. 'mdi': path.join(process.cwd(), 'node_modules/vue-material-design-icons'),
  211. // Duplicates fixes:
  212. 'apollo-link': path.join(process.cwd(), 'node_modules/apollo-link'),
  213. 'apollo-utilities': path.join(process.cwd(), 'node_modules/apollo-utilities'),
  214. 'uc.micro': path.join(process.cwd(), 'node_modules/uc.micro')
  215. },
  216. extensions: [
  217. '.js',
  218. '.json',
  219. '.jsx',
  220. '.vue'
  221. ],
  222. modules: [
  223. 'node_modules'
  224. ]
  225. },
  226. node: {
  227. fs: 'empty'
  228. },
  229. stats: {
  230. children: false,
  231. entrypoints: false
  232. },
  233. target: 'web',
  234. watch: true
  235. }