PageSourceSearch

https://socket.io/assets/js/57c04e7d.83c7e342.js

js socket.io collected 2026-09-24 07:25:36 UTC 18,754 bytes, 1 lines download raw bytes

1"use strict";(self.webpackChunksample_website=self.webpackChunksample_website||[]).push([[4741],{3905:(e,t,n)=>{n.d(t,{Zo:()=>p,kt:()=>f});var r=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function s(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?a(Object(n),!0).forEach((function(t){o(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):a(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function i(e,t){if(null==e)return{};var n,r,o=function(e,t){if(null==e)return{};var n,r,o={},a=Object.keys(e);for(r=0;r<a.length;r++)n=a[r],t.indexOf(n)>=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r<a.length;r++)n=a[r],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var c=r.createContext({}),l=function(e){var t=r.useContext(c),n=t;return e&&(n="function"==typeof e?e(t):s(s({},t),e)),n},p=function(e){var t=l(e.components);return r.createElement(c.Provider,{value:t},e.children)},u="mdxType",d={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},m=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,a=e.originalType,c=e.parentName,p=i(e,["components","mdxType","originalType","parentName"]),u=l(n),m=o,f=u["".concat(c,".").concat(m)]||u[m]||d[m]||a;return n?r.createElement(f,s(s({ref:t},p),{},{components:n})):r.createElement(f,s({ref:t},p))}));function f(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=n.length,s=new Array(a);s[0]=m;var i={};for(var c in t)hasOwnProperty.call(t,c)&&(i[c]=t[c]);i.originalType=e,i[u]="string"==typeof e?e:o,s[1]=i;for(var l=2;l<a;l++)s[l]=n[l];return r.createElement.apply(null,s)}return r.createElement.apply(null,n)}m.displayName="MDXCreateElement"}
1,9093:(e,t,n)=>{n.r(t),n.d(t,{contentTitle:()=>c,default:()=>m,frontMatter:()=>i,metadata:()=>l,toc:()=>p});var r=n(3117),o=(n(7294),n(3905)),a=n(4866),s=n(5162);const i={title:"How to use with Next.js"},c="How to use with Next.js",l={type:"mdx",permalink:"/how-to/use-with-nextjs",source:"@site/src/pages/how-to/use-with-nextjs.md",title:"How to use with Next.js",description:"This guide shows how to use Socket.IO within a Next.js application.",frontMatter:{title:"How to use with Next.js"}},p=[{value:"Server",id:"server",level:2},{value:"Client",id:"client",level:2}],u={toc:p},d="wrapper";function m(e){let{components:t,...n}=e;return(0,o.kt)(d,(0,r.Z)({},u,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h1",{id:"how-to-use-with-nextjs"},"How to use with Next.js"),(0,o.kt)("p",null,"This guide shows how to use Socket.IO within a ",(0,o.kt)("a",{parentName:"p",href:"https://nextjs.org/"},"Next.js")," application."),(0,o.kt)("admonition",{type:"caution"},(0,o.kt)("p",{parentName:"admonition"},"You won't be able to deploy your application on ",(0,o.kt)("a",{parentName:"p",href:"https://vercel.com"},"Vercel"),", as it does not support WebSocket connections."),(0,o.kt)("p",{parentName:"admonition"},"Reference: ",(0,o.kt)("a",{parentName:"p",href:"https://vercel.com/guides/do-vercel-serverless-functions-support-websocket-connections"},"https://vercel.com/guides/do-vercel-serverless-functions-support-websocket-connections"))),(0,o.kt)("h2",{id:"server"},"Server"),(0,o.kt)("p",null,"The Socket.IO server can share the same underlying HTTP server with Next.js. You just have to create a ",(0,o.kt)("inlineCode",{parentName:"p"},"server.js")," file at the root of your project:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-js",metastring:"title=server.js",title:"server.js"},'import { createServer } from "node:http";\nimport next from "next";\nimport { Server } from "socket.io";\n\nconst dev = process.env.NODE_ENV !== "production";\nconst hostname = "localhost";\nconst port = 3000;\n// when using middleware `hostname` and `port` must be provided below\nconst app = next({ dev, hostname, port });\nconst handler = app.getRequestHandler();\n\napp.prepare().then(() => {\n  const httpServer = createServer(handler);\n\n  const io = new Server(httpServer);\n\n  io.on("connection", (socket) => {\n    // ...\n  });\n\n  httpServer\n    .once("error", (err) => {\n      console.error(err);\n      process.exit(1);\n    })\n    .listen(port, () => {\n      console.log(`> Ready on http://${hostname}:${port}`);\n    });\n});\n')),(0,o.kt)("p",null,"The ",(0,o.kt)("inlineCode",{parentName:"p"},"server.js")," file becomes the entrypoint of your application:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-diff",metastring:"package.json","package.json":!0},'{\n  "scripts": {\n-   "dev": "next dev",\n+   "dev": "node server.js",\n    "build": "next build",\n-   "start": "next start",\n+   "start": "NODE_ENV=production node server.js",\n    "lint": "next lint"\n  }\n}\n')),(0,o.kt)("p",null,"And voil\xe0!"),(0,o.kt)("p",null,"Reference: ",(0,o.kt)("a",{parentName:"p",href:"https://nextjs.org/docs/pages/building-your-application/configuring/custom-server"},"https://nextjs.org/docs/pages/building-your-application/configuring/custom-server")),(0,o.kt)("admonition",{type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"This works with both the App router and the Pages router.")),(0,o.kt)("admonition",{type:"caution"},(0,o.kt)("p",{parentName:"admonition"},"From the Next.js documentation:"),(0,o.kt)("ul",{parentName:"admonition"},(0,o.kt)("li",{parentName:"ul"},"Before deciding to use a custom server, please keep in mind that it should only be used when the integrated router of Next.js can't meet your app requirements. A custom server will remove important performance optimizations, like serverless functions and ",(0,o.kt)("a",{parentName:"li",href:"https://nextjs.org/docs/pages/building-your-application/rendering/automatic-static-optimization"},"Automatic Static Optimization"),"."),(0,o.kt)("li",{parentName:"ul"},"A custom server cannot be deployed on ",(0,o.kt)("a",{parentName:"li",href:"https://vercel.com/solutions/nextjs"},"Vercel"),"."),(0,o.kt)("li",{parentName:"ul"},"Standalone output mode, does not trace custom server files and this mode outputs a separate minimal server.js file instead."))),(0,o.kt)("h2",{id:"client"},"Client"),(0,o.kt)("p",null,"On the client side, all tips from our ",(0,o.kt)("a",{parentName:"p",href:"/how-to/use-with-react"},"React guide")," are valid."),(0,o.kt)("p",null,"The only difference is that you need to exclude the Socket.IO client from server-side rendering (SSR):"),(0,o.kt)(a.Z,{groupId:"nextjs-router",mdxType:"Tabs"},(0,o.kt)(s.Z,{value:"app",label:"App router",default:!0,mdxType:"TabItem"},(0,o.kt)("p",null,"Structure:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"\u251c\u2500\u2500 src\n\u2502 \u251c\u2500\u2500 app\n\u2502 \u2502 \u2514\u2500\u2500 page.js\n\u2502 \u2514\u2500\u2500 socket.js\n\u2514\u2500\u2500 package.json\n")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-js",metastring:'title="src/socket.js"',title:'"src/socket.js"'},'"use client";\n\nimport { io } from "socket.io-client";
1\n\nexport const socket = io();\n')),(0,o.kt)("admonition",{type:"note"},(0,o.kt)("p",{parentName:"admonition"},(0,o.kt)("inlineCode",{parentName:"p"},'"use client"')," indicates that the file is part of the client bundle, and won't be server-rendered."),(0,o.kt)("p",{parentName:"admonition"},"Reference: ",(0,o.kt)("a",{parentName:"p",href:"https://nextjs.org/docs/app/building-your-application/rendering/client-components"},"https://nextjs.org/docs/app/building-your-application/rendering/client-components"))),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-js",metastring:'title="src/app/page.js"',title:'"src/app/page.js"'},'"use client";\n\nimport { useEffect, useState } from "react";\nimport { socket } from "../socket";\n\nexport default function Home() {\n  const [isConnected, setIsConnected] = useState(false);\n  const [transport, setTransport] = useState("N/A");\n\n  useEffect(() => {\n    if (socket.connected) {\n      onConnect();\n    }\n\n    function onConnect() {\n      setIsConnected(true);\n      setTransport(socket.io.engine.transport.name);\n\n      socket.io.engine.on("upgrade", (transport) => {\n        setTransport(transport.name);\n      });\n    }\n\n    function onDisconnect() {\n      setIsConnected(false);\n      setTransport("N/A");\n    }\n\n    socket.on("connect", onConnect);\n    socket.on("disconnect", onDisconnect);\n\n    return () => {\n      socket.off("connect", onConnect);\n      socket.off("disconnect", onDisconnect);\n    };\n  }, []);\n\n  return (\n    <div>\n      <p>Status: { isConnected ? "connected" : "disconnected" }</p>\n      <p>Transport: { transport }</p>\n    </div>\n  );\n}\n'))),(0,o.kt)(s.Z,{value:"pages",label:"Pages router",mdxType:"TabItem"},(0,o.kt)("p",null,"Structure:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"\u251c\u2500\u2500 src\n\u2502 \u251c\u2500\u2500 pages\n\u2502 \u2502 \u2514\u2500\u2500 index.js\n\u2502 \u2514\u2500\u2500 socket.js\n\u2514\u2500\u2500 package.json\n")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-js",metastring:'title="src/socket.js"',title:'"src/socket.js"'},'import { io } from "socket.io-client";\n\nconst isBrowser = typeof window !== "undefined";\n\nexport const socket = isBrowser ? io() : {};\n')),(0,o.kt)("admonition",{type:"note"},(0,o.kt)("p",{parentName:"admonition"},"The ",(0,o.kt)("inlineCode",{parentName:"p"},"isBrowser")," check is important, as it prevents Next.js from trying to create a Socket.IO client when doing server-side rendering."),(0,o.kt)("p",{parentName:"admonition"},"Reference: ",(0,o.kt)("a",{parentName:"p",href:"https://nextjs.org/docs/pages/building-your-application/rendering/client-side-rendering"},"https://nextjs.org/docs/pages/building-your-application/rendering/client-side-rendering"))),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-js",metastring:'title="src/pages/index.js"',title:'"src/pages/index.js"'},'import { useEffect, useState } from "react";\nimport { socket } from "../socket";\n\nexport default function Home() {\n  const [isConnected, setIsConnected] = useState(false);\n  const [transport, setTransport] = useState("N/A");\n\n  useEffect(() => {\n    if (socket.connected) {\n      onConnect();\n    }\n\n    function onConnect() {\n      setIsConnected(true);\n      setTransport(socket.io.engine.transport.name);\n\n      socket.io.engine.on("upgrade", (transport) => {\n        setTransport(transport.name);\n      });\n    }\n\n    function onDisconnect() {\n      setIsConnected(false);\n      setTransport("N/A");\n    }\n\n    socket.on("connect", onConnect);\n    socket.on("disconnect", onDisconnect);\n\n    return () => {\n      socket.off("connect", onConnect);\n      socket.off("disconnect", onDisconnect);\n    };\n  }, []);\n\n  return (\n    <div>\n      <p>Status: { isConnected ? "connected" : "disconnected" }</p>\n      <p>Transport: { transport }</p>\n    </div>\n  );\n}\n')))),(0,o.kt)("admonition",{type:"note"},(0,o.kt)("p",{parentName:"admonition"},"We could have used:"),(0,o.kt)("pre",{parentName:"admonition"},(0,o.kt)("code",{parentName:"pre",className:"language-js"},"const [isConnected, setIsConnected] = useState(socket.connected);\n")),(0,o.kt)("p",{parentName:"admonition"},"instead of:"),(0,o.kt)("pre",{parentName:"admonition"},(0,o.kt)("code",{parentName:"pre",className:"language-js"},"const [isConnected, setIsConnected] = useState(false);\n\nuseEffect(() =>
1 {\n  if (socket.connected) {\n    onConnect();\n  }\n  // ...\n});\n")),(0,o.kt)("p",{parentName:"admonition"},"but this triggers some warnings from the Next.js compiler, as the client-rendered page may not match the server-rendered output."),(0,o.kt)("blockquote",{parentName:"admonition"},(0,o.kt)("p",{parentName:"blockquote"},"Uncaught Error: Text content does not match server-rendered HTML."))),(0,o.kt)("p",null,"In the example above, the ",(0,o.kt)("inlineCode",{parentName:"p"},"transport")," variable is the low-level transport used to establish the Socket.IO connection, which can be either:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"HTTP long-polling (",(0,o.kt)("inlineCode",{parentName:"li"},'"polling"'),")"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("a",{parentName:"li",href:"https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API"},"WebSocket")," (",(0,o.kt)("inlineCode",{parentName:"li"},'"websocket"'),")"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("a",{parentName:"li",href:"https://developer.mozilla.org/en-US/docs/Web/API/WebTransport_API"},"WebTransport")," (",(0,o.kt)("inlineCode",{parentName:"li"},'"webtransport"'),")")),(0,o.kt)("p",null,"If everything went well, you should see:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"Status: connected\nTransport: websocket\n")),(0,o.kt)("p",null,"You can then exchange messages between the Socket.IO server and client with:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"socket.emit()")," to send messages")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-js"},'socket.emit("hello", "world");\n')),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"socket.on()")," to receive messages")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-js"},'socket.on("hello", (value) => {\n  // ...\n});\n')),(0,o.kt)("p",null,"That's all folks, thanks for reading!"),(0,o.kt)("p",null,(0,o.kt)("a",{parentName:"p",href:"/get-started/"},"Back to the list of examples")))}m.isMDXComponent=!0},5162:(e,t,n)=>{n.d(t,{Z:()=>s});var r=n(7294),o=n(4334);const a={tabItem:"tabItem_Ymn6"};function s(e){let{children:t,hidden:n,className:s}=e;return r.createElement("div",{role:"tabpanel",className:(0,o.Z)(a.tabItem,s),hidden:n},t)}},4866:(e,t,n)=>{n.d(t,{Z:()=>y});var r=n(3117),o=n(7294),a=n(4334),s=n(2466),i=n(6550),c=n(1980),l=n(7392),p=n(12);function u(e){return function(e){return o.Children.map(e,(e=>{if(!e||(0,o.isValidElement)(e)&&function(e){const{props:t}=e;return!!t&&"object"==typeof t&&"value"in t}(e))return e;throw new Error(`Docusaurus error: Bad <Tabs> child <${"string"==typeof e.type?e.type:e.type.name}>: all children of the <Tabs> component should be <TabItem>, and every <TabItem> should have a unique "value" prop.`)}))?.filter(Boolean)??[]}(e).map((e=>{let{props:{value:t,label:n,attributes:r,default:o}}=e;return{value:t,label:n,attributes:r,default:o}}))}function d(e){const{values:t,children:n}=e;return(0,o.useMemo)((()=>{const e=t??u(n);return function(e){const t=(0,l.l)(e,((e,t)=>e.value===t.value));if(t.length>0)throw new Error(`Docusaurus error: Duplicate values "${t.map((e=>e.value)).join(", ")}" found in <Tabs>. Every value needs to be unique.`)}(e),e}),[t,n])}function m(e){let{value:t,tabValues:n}=e;return n.some((e=>e.value===t))}function f(e){let{queryString:t=!1,groupId:n}=e;const r=(0,i.k6)(),a=function(e){let{queryString:t=!1,groupId:n}=e;if("string"==typeof t)return t;if(!1===t)return null;if(!0===t&&!n)throw new Error('Docusaurus error: The <Tabs> component groupId prop is required if queryString=true, because this value is used as the search param name. You can also provide an explicit value such as queryString="my-search-param".');return n??null}({queryString:t,groupId:n});return[(0,c._X)(a),(0,o.useCallback)((e=>{if(!a)return;const t=new URLSearchParams(r.location.search);t.set(a,e),r.replace({...r.location,search:t.toString()})}),[a,r])]}function k(e){const{defaultValue:t,queryString:n=!1,groupId:r}=e,a=d(e),[s,i]=(0,o.useState)((()=>function(e){let{defaultValue:t,tabValues:n}=e;if(0===n.length)throw new Error("Docusaurus error: the <Tabs> component requires at least one <TabItem> children component");if(t){if(!m({value:t,tabValues:n}))throw new Error(`Docusaurus error: The <Tabs> has a defaultValue "${t}" but none of its children has the corresponding value. Available values are: ${n.map((e=>e.value)).join(", ")}. If you intend to show no default tab, use defaultValue={null} instead.`);return t}const r=n.find((e=>e.default))??n[0];if(!r)throw new Error("Unexpected error: 0 tabValues");return r.value}({defaultValue:t,tabValues:a}))),[c,l]=f({queryString:n,groupId:r}),[u,k]=function(e){let{groupId:t}=e;const n=function(e){return e?`docusaurus.tab.${e}`:null}(t),[r,a]=(0,p.Nk)(n);return[r,(0,o.useCallback)((e=>{n&&a.set(e)}),[n,a])]}({groupId:r}),h=(()=>{const e=c??u;return m({value:e,tabValues:a})?e:null})();(0,o.useLayoutEffect)((()=>{h&&i(h)}),[h]);return{selectedValue:s,selectValue:(0,o.useCallback)((e=>{if(!m({value:e,tabValues:a}))throw new Error(`Can't select invalid tab value=${e}`);i(e),l(e),k(e)}),[l,k,a]),tabValues:a}}var h=n(2389);const g={tabList:"tabList__CuJ",tabItem:"tabItem_LNqP"};function b(e){let{className:t,block:n,selectedValue:i,selectValue:c,tabValues:l}=e;const p=[],{blockElementScrollPositionUntilNextRender:u}=(0,s.o5)(),d=e=>{const t=e.currentTarget,n=p.indexOf(t),r=l[n].value;r!==i&&(u(t),c(r))},m=e=>{let t=null;switch(e.key){case"Enter":d(e);break;case"ArrowRight":{const n=p.indexOf(e.currentTarget)+1;t=p[n]??p[0];break}case"ArrowLeft":{const n=p.indexOf(e.currentTarget)-1;t=p[n]??p[p.length-1];break}}t?.focus()};return o.createElement("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,a.Z)("tabs",{"tabs--block":n},t)},l.map((e=>{let{value:t,label:n,attributes:s}=e;return o.createElement("li",(0,r.Z)({role:"tab",tabIndex:i===t?0:-1,"aria-selected":i===t,key:t,ref:e=>p.push(e),onKeyDown:m,onClick:d},s,{className:(0,a.Z)("tabs__item",g.tabItem,s?.className,{"tabs__item--active":i===t})}),n??t)})))}function v(e){let{lazy:t,children:n,selectedValue:r}=e;
1const a=(Array.isArray(n)?n:[n]).filter(Boolean);if(t){const e=a.find((e=>e.props.value===r));return e?(0,o.cloneElement)(e,{className:"margin-top--md"}):null}return o.createElement("div",{className:"margin-top--md"},a.map(((e,t)=>(0,o.cloneElement)(e,{key:t,hidden:e.props.value!==r}))))}function N(e){const t=k(e);return o.createElement("div",{className:(0,a.Z)("tabs-container",g.tabList)},o.createElement(b,(0,r.Z)({},e,t)),o.createElement(v,(0,r.Z)({},e,t)))}function y(e){const t=(0,h.Z)();return o.createElement(N,(0,r.Z)({key:String(t)},e))}}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.