server.js 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. /**
  2. * More info about this file:
  3. * https://v2.quasar.dev/quasar-cli-vite/developing-ssr/ssr-webserver
  4. *
  5. * Runs in Node context.
  6. */
  7. /**
  8. * Make sure to yarn add / npm install (in your project root)
  9. * anything you import here (except for express and compression).
  10. */
  11. import express from 'express'
  12. import compression from 'compression'
  13. import {
  14. ssrClose,
  15. ssrCreate,
  16. ssrListen,
  17. ssrRenderPreloadTag,
  18. ssrServeStaticContent
  19. } from 'quasar/wrappers'
  20. const heapMemoryAllocationInterval = parseInt(process.env.HEAP_MEMORY_ALLOCATION_INTERVAL)
  21. const maxHeapMemoryAllocationInPercent = parseInt(process.env.MAX_HEAP_MEMORY_ALLOCATION_IN_PERCENT)
  22. /**
  23. * Create your webserver and return its instance.
  24. * If needed, prepare your webserver to receive
  25. * connect-like middlewares.
  26. *
  27. * Should NOT be async!
  28. */
  29. export const create = ssrCreate((/* { ... } */) => {
  30. const app = express()
  31. const heapMemoryLimitAllocation = 4.1 * 1024
  32. setInterval(()=>{
  33. const memoryResidentSetSizeInMB = process.memoryUsage().rss/1000000
  34. const heapMemoryAllocation = (memoryResidentSetSizeInMB / heapMemoryLimitAllocation) * 100
  35. if (heapMemoryAllocation > maxHeapMemoryAllocationInPercent) {
  36. console.log('memoryResidentSetSizeInMB: ', memoryResidentSetSizeInMB)
  37. console.log('heapMemoryAllocation: ', heapMemoryAllocation)
  38. process.exit(110)
  39. }
  40. }, heapMemoryAllocationInterval)
  41. // app.use(audit({
  42. // doubleAudit: true,
  43. // request: {
  44. // excludeHeaders: ['*'], // Exclude all headers from responses,
  45. // excludeBody: ['*'], // Exclude all body from responses
  46. // },
  47. // response: {
  48. // excludeHeaders: ['*'], // Exclude all headers from responses,
  49. // excludeBody: ['*'], // Exclude all body from responses
  50. // maxBodyLength: 1 // limit length to 50 chars + '...'
  51. // }
  52. // }))
  53. // attackers can use this header to detect apps running Express
  54. // and then launch specifically-targeted attacks
  55. app.disable('x-powered-by')
  56. // place here any middlewares that
  57. // absolutely need to run before anything else
  58. if (process.env.PROD) {
  59. app.use(compression())
  60. }
  61. return app
  62. })
  63. /**
  64. * You need to make the server listen to the indicated port
  65. * and return the listening instance or whatever you need to
  66. * close the server with.
  67. *
  68. * The "listenResult" param for the "close()" definition below
  69. * is what you return here.
  70. *
  71. * For production, you can instead export your
  72. * handler for serverless use or whatever else fits your needs.
  73. */
  74. export const listen = ssrListen(async ({ app, port, isReady }) => {
  75. await isReady()
  76. return app.listen(port, () => {
  77. if (process.env.PROD) {
  78. console.log('Server listening at port ' + port)
  79. }
  80. })
  81. })
  82. /**
  83. * Should close the server and free up any resources.
  84. * Will be used on development only when the server needs
  85. * to be rebooted.
  86. *
  87. * Should you need the result of the "listen()" call above,
  88. * you can use the "listenResult" param.
  89. *
  90. * Can be async.
  91. */
  92. export const close = ssrClose(({ listenResult }) => {
  93. return listenResult.close()
  94. })
  95. const maxAge = process.env.DEV
  96. ? 0
  97. : 1000 * 60 * 60 * 24 * 30
  98. /**
  99. * Should return middleware that serves the indicated path
  100. * with static content.
  101. */
  102. export const serveStaticContent = ssrServeStaticContent((path, opts) => {
  103. return express.static(path, {
  104. maxAge,
  105. ...opts
  106. })
  107. })
  108. const jsRE = /\.js$/
  109. const cssRE = /\.css$/
  110. const woffRE = /\.woff$/
  111. const woff2RE = /\.woff2$/
  112. const gifRE = /\.gif$/
  113. const jpgRE = /\.jpe?g$/
  114. const pngRE = /\.png$/
  115. /**
  116. * Should return a String with HTML output
  117. * (if any) for preloading indicated file
  118. */
  119. export const renderPreloadTag = ssrRenderPreloadTag((file) => {
  120. if (jsRE.test(file) === true) {
  121. return `<link rel="modulepreload" href="${file}" crossorigin>`
  122. }
  123. if (cssRE.test(file) === true) {
  124. return `<link rel="stylesheet" href="${file}">`
  125. }
  126. if (woffRE.test(file) === true) {
  127. return `<link rel="preload" href="${file}" as="font" type="font/woff" crossorigin>`
  128. }
  129. if (woff2RE.test(file) === true) {
  130. return `<link rel="preload" href="${file}" as="font" type="font/woff2" crossorigin>`
  131. }
  132. if (gifRE.test(file) === true) {
  133. return `<link rel="preload" href="${file}" as="image" type="image/gif">`
  134. }
  135. if (jpgRE.test(file) === true) {
  136. return `<link rel="preload" href="${file}" as="image" type="image/jpeg">`
  137. }
  138. if (pngRE.test(file) === true) {
  139. return `<link rel="preload" href="${file}" as="image" type="image/png">`
  140. }
  141. return ''
  142. })