PageSourceSearch

https://relay.dev/assets/js/25430d76.0769c0af.js

js relay.dev collected 2026-10-02 03:12:41 UTC 15,164 bytes, 1 lines download raw bytes

1"use strict";(self.webpackChunk=self.webpackChunk||[]).push([["17037"],{15291(e,t,n){n.r(t),n.d(t,{metadata:()=>i,default:()=>p,frontMatter:()=>o,contentTitle:()=>c,toc:()=>l,assets:()=>d});var i=JSON.parse('{"id":"principles-and-architecture/compiler-architecture","title":"Compiler Architecture","description":"Relay compiler architecture guide","source":"@site/versioned_docs/version-v15.0.0/principles-and-architecture/compiler-architecture.md","sourceDirName":"principles-and-architecture","slug":"/principles-and-architecture/compiler-architecture/","permalink":"/docs/v15.0.0/principles-and-architecture/compiler-architecture/","draft":false,"unlisted":false,"editUrl":"https://github.com/facebook/relay/tree/main/website/versioned_docs/version-v15.0.0/principles-and-architecture/compiler-architecture.md","tags":[],"version":"v15.0.0","frontMatter":{"id":"compiler-architecture","title":"Compiler Architecture","slug":"/principles-and-architecture/compiler-architecture/","description":"Relay compiler architecture guide","keywords":["compiler","architecture","transform"]},"sidebar":"docs","previous":{"title":"Architecture Overview","permalink":"/docs/v15.0.0/principles-and-architecture/architecture-overview/"},"next":{"title":"Runtime Architecture","permalink":"/docs/v15.0.0/principles-and-architecture/runtime-architecture/"}}'),r=n(74848),a=n(28453),s=n(86898);let o={id:"compiler-architecture",title:"Compiler Architecture",slug:"/principles-and-architecture/compiler-architecture/",description:"Relay compiler architecture guide",keywords:["compiler","architecture","transform"]},c,d={},l=[{value:"Data Flow",id:"data-flow",level:2},{value:"Data Types & Modules",id:"data-types--modules",level:2},{value:"Transforms",id:"transforms",level:2}];function h(e){let t={code:"code",h2:"h2",li:"li",ol:"ol",p:"p",pre:"pre",ul:"ul",...(0,a.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.p,{children:"The compiler is a set of modules designed to extract GraphQL documents from across a codebase, transform/optimize them, and generate build artifacts. Examples of common types of artifacts include optimized GraphQL to persist to your server, runtime representations of the queries for use with GraphQL clients such as the Relay runtime, or generated source code for use with GraphQL frameworks for compiled languages (Java/Swift/etc)."}),"\n",(0,r.jsx)(t.h2,{id:"data-flow",children:"Data Flow"}),"\n",(0,r.jsx)(t.p,{children:"The high-level flow of data through the compiler is represented in the following diagram:"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{children:"\n                   \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n                   \u2502   GraphQL   \u2502\u2502   Schema    \u2502\n                   \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n                          \u2502              \u2502              parse\n                          \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n                                  \u25BC\n                   \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n                   \u2502      CompilerContext       \u2502\n                   \u2502                            \u2502\n                   \u2502   \u250C\u2500\u2500\u2500\u2500\u2500\u2510 \u250C\u2500\u2500\u2500\u2500\u2500\u2510 \u250C\u2500\u2500\u2500\u2500\u2500\u2510  \u2502\u2500\u2500\u2510\n                   \u2502   \u2502 IR  \u2502 \u2502 IR  \u2502 \u2502 ... \u2502  \u2502  \u2502\n                   \u2502   \u2514\u2500\u2500\u2500\u2500\u2500\u2518 \u2514\u2500\u2500\u2500\u2500\u2500\u2518 \u2514\u2500\u2500\u2500\u2500\u2500\u2518  \u2502  \u2502\n                   \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518  \u2502  transform/\n                          \u2502    \u2502      \u25B2            \u2502   optimize\n                          \u2502    \u2502      \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n                          \u2502    \u2502\n                          \u2502    \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n                          \u2502  print        \u2502  codegen\n                          \u25BC               \u25BC\n                   \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510 \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n                   \u2502   GraphQL   \u2502 \u2502  Artifacts  \u2502\n                   \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n"})}),"\n",(0,r.jsxs)(t.ol,{children:["\n",(0,r.jsx)(t.li,{children:'GraphQL text is extracted from source files and "parsed" into an intermediate representation (IR) using information from the schema.'}),"\n",(0,r.jsx)(t.li,{children:"The set of IR documents forms a CompilerContext, which is then transformed and optimized."}),"\n",(0,r.jsx)(t.li,{children:"Finally, GraphQL is printed (e.g. to files, saved to a database, etc) and any artifacts are generated."}),"\n"]}),"\n",(0,r.jsx)(t.h2,{id:"data-types--modules",children:"Data Types & Modules"}),"\n",(0,r.jsx)(t.p,{children:"The compiler module is composed of a set of core building blocks as well as a helper that packages them together in an easy to use API. Some of the main data types and modules in the compiler are as follows:"}),"\n",(0,r.jsxs)(t.ul,{children:["\n",(0,r.jsxs)(t.li,{children:[(0,r.jsx)(t.code,{children:"IR"})," (Intermediate Representation): an (effectively immutable) representation of a GraphQL document (query, fragment, field, etc) as a tree structure, including type information from a schema. Compared to the standard GraphQL AST (produced by e.g. ",(0,r.jsx)(t.code,{children:"graphql-js"}),") the main difference is that it encodes more of the semantics of GraphQL. For example, conditional branches (",(0,r.jsx)(t.code,{children:"@include"}
1)," and ",(0,r.jsx)(t.code,{children:"@skip"}),") are represented directly, making it easier to target optimizations for these directives (One such optimization is to merge sibling fields with the same condition, potentially reducing the number of conditionals that must be evaluated at runtime)."]}),"\n",(0,r.jsxs)(t.li,{children:[(0,r.jsx)(t.code,{children:"CompilerContext"}),": an immutable representation of a corpus of GraphQL documents. It contains the schema and a mapping of document names to document representations (as IR, see above)."]}),"\n",(0,r.jsxs)(t.li,{children:[(0,r.jsx)(t.code,{children:"Transform"}),': a "map"-like function that accepts a ',(0,r.jsx)(t.code,{children:"CompilerContext"})," as input and returns a new, modified context as output. Examples below."]}),"\n",(0,r.jsxs)(t.li,{children:[(0,r.jsx)(t.code,{children:"Parser"}),": Converts a GraphQL schema and raw GraphQL text into typed IR objects."]}),"\n",(0,r.jsxs)(t.li,{children:[(0,r.jsx)(t.code,{children:"Printer"}),": a function that accepts IR and converts it to a GraphQL string."]}),"\n"]}),"\n",(0,r.jsxs)(t.p,{children:["The ",(0,r.jsx)(t.code,{children:"RelayCompiler"})," module is a helper class that demonstrates one way of combining these primitives. It takes IR transforms, and given IR definitions, constructs a CompilerContext from them, transforming them, and generating output artifacts intended for use with Relay runtime."]}),"\n",(0,r.jsx)(t.h2,{id:"transforms",children:"Transforms"}),"\n",(0,r.jsx)(t.p,{children:"One of the main goals of the compiler is to provide a consistent platform for writing tools that transform or optimize GraphQL. This includes the ability to experiment with new directives by transforming them away at compile time. Transform functions should typically perform a single type of modification - it's expected that an app will have multiple transforms configured in the compiler instance."}),"\n",(0,r.jsx)(t.p,{children:"Here are a few examples of some of the included transforms:"}),"\n",(0,r.jsxs)(t.ul,{children:["\n",(0,r.jsxs)(t.li,{children:[(0,r.jsx)(t.code,{children:"FlattenTransform"}),": Reduces extraneous levels of indirection in a query, inlining fields from anonymous fragments wherever they match the parent type. This can be beneficial when generating code to read the results of a query or process query results, as it reduces duplicate field processing. For example:"]}),"\n"]}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{children:"# before: `id` is processed twice\nfoo { # type FooType\n   id\n   ... on FooType { # matches the parent type, so this is extraneous\n     id\n   }\n }\n\n # after: `id` is processed once\n foo {\n   id\n }\n"})}),"\n",(0,r.jsxs)(t.ul,{children:["\n",(0,r.jsxs)(t.li,{children:[(0,r.jsx)(t.code,{children:"SkipRedundantNodeTransform"}),": A more advanced version of flattening, this eliminates more complex cases of field duplication such as when a field is fetched both unconditionally and conditionally, or is fetched by two different sub-fragments. For example:"]}),"\n"]}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{children:"# before: `id` processed up to 2x\nfoo {\n  bar {\n    id\n  }\n  ... on FooType @include(if: $cond) { # can't be flattened due to conditional\n    id # but this field is guaranteed to be fetched regardless\n  }\n}\n\n# after: `id` processed at most once\nfoo {\n  bar {\n    id\n  }\n}\n"})}),"\n",(0,r.jsx)(s.A,{})]})}function p(e={}){let{wrapper:t}={...(0,a.R)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(h,{...e})}):h(e)}},86898(e,t,n){n.d(t,{A:()=>u});var i=n(74848),r=n(95310),a=n(17352),s=n(96540);function o(){let e=window.encodeURI(JSON.stringify({title:"Feedback about "+window.location.pathname,description:"**!!! Required !!!**\n\nPlease modify the task description to let us know how the docs can be improved.\n\n**Please do not ask support questions via this form! Instead, ask in fburl.com/relay_support**",tag_ids:{add:[0xac96423e5b680,0x64079768ac750]}}));window.open("https://www.internalfb.com/tasks/?n="+e)}function c({children:e}){return(0,i.jsxs)("div",{className:"docsRating",id:"docsRating",children:[(0,i.jsx)("hr",{}),e]})}let d=()=>{let[e,t]=s.useState(!1),n=e=>{t(!0),window.ga&&window.ga("send",{hitType:"event",eventCategory:"button",eventAction:"feedback",eventValue:e})};return e?"Thank you for letting us know!":(0,i.jsxs)(i.Fragment,{children:["Is this page useful?",(0,i.jsx)("svg",{className:"i_thumbsup",alt:"Like",id:"docsRating-like",xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 81.13 89.76",onClick:()=>n(1),children:(0,i.jsx)("path",{d:"M22.9 6a18.57 18.57 0 002.67 8.4 25.72 25.72 0 008.65 7.66c3.86 2 8.67 7.13 13.51 11 3.86 3.11 8.57 7.11 11.54 8.45s13.59.26 14.64 1.17c1.88 1.63 1.55 9-.11 15.25-1.61 5.86-5.96 10.55-6.48 16.86-.4 4.83-2.7 4.88-10.93 4.88h-1.35c-3.82 0-8.24 2.93-12.92 3.62a68 68 0 01-9.73.5c-3.57 0-7.86-.08-13.25-.08-3.56 0-4.71-1.83-4.71-4.48h8.42a3.51 3.51 0 000-7H12.28a2.89 2.89 0 01-2.88-2.88 1.91 1.91 0 01.77-1.78h16.46a3.51 3.51 0 000-7H12.29c-3.21 0-4.84-1.83-4.84-4a6.41 6.41 0 011.17-3.78h19.06a3.5 3.5 0 100-7H9.75A3.51 3.51 0 016 42.27a3.45 3.45 0 013.75-3.48h13.11c5.61 0 7.71-3 5.71-5.52-4.43-4.74-10.84-12.62-11-18.71-.15-6.51 2.6-7.83 5.36-8.56m0-6a6.18 6.18 0 00-1.53.2c-6.69 1.77-10 6.65-9.82 14.5.08 5.09 2.99 11.18 8.52 18.09H9.74a9.52 9.52 0 00-6.23 16.9 12.52 12.52 0 00-2.07 6.84 9.64 9.64 0 003.65 7.7 7.85 7.85 0 00-1.7 5.13 8.9 8.9 0 005.3 8.13 6 6 0 00-.26 1.76c0 6.37 4.2 10.48 10.71 10.48h13.25a73.75 73.75 0 0010.6-.56 35.89 35.89 0 007.58-2.18 17.83 17.83 0 014.48-1.34h1.35c4.69 0 7.79 0 10.5-1 3.85-1.44 6-4.59 6.41-9.38.2-2.46 1.42-4.85 2.84-7.62a41.3 41.3 0 003.42-8.13 48 48 0 001.59-10.79c.1-5.13-1-8.48-3.35-10.55-2.16-1.87-4.64-1.87-9.6-1.88a46.86 46.86 0 01-6.64-.29c-1.92-.94-5.72-4-8.51-6.3l-1.58-1.28c-1.6-1.3-3.27-2.79-4.87-4.23-3.33-3-6.47-5.79-9.61-7.45a20.2 20.2 0 01-6.43-5.53 12.44 12.44 0 01-1.72-5.36 6 6 0 00-6-5.86z"})}),(0,i.jsx)("svg",{className:"i_thumbsdown",alt:"Dislike",id:"docsRating-dislike",xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 81.13 89.76",onClick:()=>n(0),children:(0,i.jsx)("path",{d:"M22.9 6a18.57 18.57 0 002.67 8.4 25.72 25.72 0 008.65 7.66c3.86 2 8.67 7.13 13.51 11 3.86 3.11 8.57 7.11 11.54 8.45s13.59.26 14.64 1.17c1.88 1.63 1.55 9-.11 15.25-1.61 5.86-5.96 10.55-6.48 16.86-.4 4.83-2.7 4.88-10.93 4.88h-1.35c-3.82 0-8.24 2.93-12.92 3.62a68 68 0 01-9.73.5c-3.57 0-7.86-.08-13.25-.08-3.56 0-4.71-1.83-4.71-4.48h8.42a3.51 3.51 0 000-7H12.28a2.89 2.89 0 01-2.88-2.88 1.91 1.91 0 01.77-1.78h16.46a3.51 3.51 0 000-7H12.29c-3.21 0-4.84-1.83-4.84-4a6.41 6.41 0 011.17-3.78h19.06a3.5 3.5 0 100-7H9.75A3.51 3.51 0 016 42.27a3.45 3.45 0 013.75-3.48h13.11c5.61 0 7.71-3 5.71-5.52-4.43-4.74-10.84-12.62-11-18.71-.15-6.51 2.6-7.83 5.36-8.56m0-6a6.18 6.18 0 00-1.53.2c-6.69 1.77-10 6.65-9.82 14.5.08 5.09 2.99 11.18 8.52 18.09H9.74a9.52 9.52 0 00-6.23 16.9 12.52 12.52 0 00-2.07 6.84 9.64 9.64 0 003.65 7.7 7.85 7.85 0 00-1.7 5.13 8.9 8.9 0 005.3 8.13 6 6 0 00-.26 1.76c0 6.37 4.2 10.48 10.71 10.48h13.25a73.75 73.75 0 0010.6-.56 35.89 35.89 0 007.58-2.18 17.83 17.83 0 014.48-1.34h1.35c4.69 0 7.79 0 10.5-1 3.85-1.44 6-4.59 6.41-9.38.2-2.46 1.42-4.85 2.84-7.62a41.3 41.3 0 003.42-8.13 48 48 0 001.59-10.79c.1-5.13-1-8.48-3.35-10.55-2.16-1.87-4.64-1.87-9.6-1.88a46.86 46.86 0 01-6.64-.29c-1.92-.94-5.72-4-8.51-6.3l-1.58-1.28c-1.6-1.3-3.27-2.79-4.87-4.23-3.33-3-6.47-5.79-9.61-7.45a20.2 20.2 0 01-6.43-5.53 12.44 12.44 0 01-1.72-5.36 6 6 0 00-6-5.86z"})})]})},l=()=>(0,i.jsxs)("p",{children:["Let us know how these docs can be improved by",(0,i.jsx)("a",{className:"button",role:"button",tabIndex:0,onClick:o,children:"Filing a task"})]}),h=()=>(0,i.jsxs)("p",{children:["Help us make the site even better by"," ",(0,i.jsx)(r.default,{to:"https://www.surveymonkey.com/r/FYC9TCJ",children:"answering a few quick questions"}),"."]}),p=()=>(0,i.jsxs)(c,{children:[(0,i.jsx)(l,{}),(0,i.jsx)(d,{}),(0,i.jsx)(h,{})]}),m=()=>(0,i.jsxs)(c,{children:[(0,i.jsx)(d,{}),(0,i.jsx)(h,{})]}),u=()=>(0,a.fbContent)({internal:(0,i.jsx)(p,{}),external:(0,i.jsx)(m,{})})},28453(e,t,n){n.d(t,{R:()=>s,x:()=>o});var i=n(96540);let r={},a=i.createContext(r);function s(e){let t=i.useContext(a);return i.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:s(e.components),i.createElement(a.Provider,{value:t},e.children)}}}]);

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.