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.

266 lines
6.3 KiB

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