[{"data":1,"prerenderedAt":1644},["Reactive",2],{"blog/firebase-web-notifications-tutorial-2023":3},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"draft":6,"external":6,"category":10,"tags":12,"date":19,"body":20,"_type":1638,"_id":1639,"_source":1640,"_file":1641,"_stem":1642,"_extension":1643},"/blog/firebase-web-notifications-tutorial-2023","blog",false,"","Firebase Web Notifications - How to set it up and receive notifications","How to register and receive notifications with Firebase. Repository and code examples. With ViteJS",[11],"Vue",[13,14,15,16,17,18],"firebase","fcm","notifications","web","javascript","vitejs","2023-02-05T00:00:00.000Z",{"type":21,"children":22,"toc":1629},"root",[23,48,55,60,67,92,97,110,120,131,470,491,497,509,530,542,548,555,560,565,584,589,605,610,1030,1035,1126,1152,1158,1171,1176,1186,1490,1501,1586,1599,1605,1610,1623],{"type":24,"tag":25,"props":26,"children":27},"element","blockquote",{},[28,36],{"type":24,"tag":29,"props":30,"children":32},"h5",{"id":31},"tldr-here-is-the-repository-with-the-code",[33],{"type":34,"value":35},"text","TLDR; Here is the repository with the code",{"type":24,"tag":37,"props":38,"children":39},"p",{},[40],{"type":24,"tag":41,"props":42,"children":46},"a",{"href":43,"rel":44},"https://github.com/andreitere/firebase-web-notifications",[45],"nofollow",[47],{"type":34,"value":43},{"type":24,"tag":49,"props":50,"children":52},"h1",{"id":51},"introduction",[53],{"type":34,"value":54},"Introduction",{"type":24,"tag":37,"props":56,"children":57},{},[58],{"type":34,"value":59},"What initially proved to be simple from a setup perspective for local development, generating the prod bundle involved some challenges.\nThe basic steps are straightforward, but productionizing the setup a bit was tricky.",{"type":24,"tag":61,"props":62,"children":64},"h2",{"id":63},"setting-up-the-firebase-project",[65],{"type":34,"value":66},"Setting up the firebase project",{"type":24,"tag":68,"props":69,"children":70},"ol",{},[71,82],{"type":24,"tag":72,"props":73,"children":74},"li",{},[75],{"type":24,"tag":41,"props":76,"children":79},{"href":77,"rel":78},"https://firebase.google.com/docs/web/setup#create-project",[45],[80],{"type":34,"value":81},"Create your firebase project",{"type":24,"tag":72,"props":83,"children":84},{},[85],{"type":24,"tag":41,"props":86,"children":89},{"href":87,"rel":88},"https://firebase.google.com/docs/web/setup#register-app",[45],[90],{"type":34,"value":91},"Register your app",{"type":24,"tag":37,"props":93,"children":94},{},[95],{"type":34,"value":96},"At this point you will have the firebaseConfig object with all the require credentials.",{"type":24,"tag":37,"props":98,"children":99},{},[100,102,108],{"type":34,"value":101},"As I am using vite and you will probably also want to, i'm filling an ",{"type":24,"tag":103,"props":104,"children":105},"strong",{},[106],{"type":34,"value":107},".env",{"type":34,"value":109}," file with all the settings so that they will be filled properly on build.",{"type":24,"tag":111,"props":112,"children":114},"pre",{"code":113},"VITE_APP_FIREBASE_API_KEY=\"apiKey\"\nVITE_APP_PROJECT_ID=\"projectId\"\nVITE_APP_FIREBASE_MESSAGING_SENDER_ID=\"messagingSenderId\"\nVITE_APP_FIREBASE_APP_ID=\"appId\"\nVITE_APP_FIREBASE_VAPKEY=\"VAPKEY\"\nVITE_APP_FIREBASE_MEASUREMENT_ID=\"measurementId\"\nVITE_APP_FIREBASE_STORAGE_BUCKET=\"storageBucket\"\nVITE_APP_FIREABASE_DATABASE_URL=\"databaseURL\"\nVITE_APP_FIREABASE_AUTH_DOMAIN=\"authDomain\"\n",[115],{"type":24,"tag":116,"props":117,"children":118},"code",{"__ignoreMap":7},[119],{"type":34,"value":113},{"type":24,"tag":37,"props":121,"children":122},{},[123,125],{"type":34,"value":124},"These all will be replaced in ",{"type":24,"tag":116,"props":126,"children":128},{"className":127},[],[129],{"type":34,"value":130},"firebase.config.js",{"type":24,"tag":111,"props":132,"children":136},{"code":133,"language":134,"meta":7,"className":135,"style":7},"const firebaseConfig = {\n  apiKey: import.meta.env.VITE_APP_FIREBASE_API_KEY,\n  authDomain: import.meta.env.VITE_APP_FIREABASE_AUTH_DOMAIN,\n  databaseURL: import.meta.env.VITE_APP_FIREABASE_DATABASE_URL,\n  projectId: import.meta.env.VITE_APP_PROJECT_ID,\n  storageBucket: import.meta.env.VITE_APP_FIREBASE_STORAGE_BUCKET,\n  messagingSenderId: import.meta.env.VITE_APP_FIREBASE_MESSAGING_SENDER_ID,\n  appId: import.meta.env.VITE_APP_FIREBASE_APP_ID,\n  measurementId: import.meta.env.VITE_APP_FIREBASE_MEASUREMENT_ID\n};\nexport default firebaseConfig;\n","js","language-js shiki shiki-themes github-dark",[137],{"type":24,"tag":116,"props":138,"children":139},{"__ignoreMap":7},[140,169,208,242,276,310,344,378,412,442,451],{"type":24,"tag":141,"props":142,"children":145},"span",{"class":143,"line":144},"line",1,[146,152,158,163],{"type":24,"tag":141,"props":147,"children":149},{"style":148},"--shiki-default:#F97583",[150],{"type":34,"value":151},"const",{"type":24,"tag":141,"props":153,"children":155},{"style":154},"--shiki-default:#79B8FF",[156],{"type":34,"value":157}," firebaseConfig",{"type":24,"tag":141,"props":159,"children":160},{"style":148},[161],{"type":34,"value":162}," =",{"type":24,"tag":141,"props":164,"children":166},{"style":165},"--shiki-default:#E1E4E8",[167],{"type":34,"value":168}," {\n",{"type":24,"tag":141,"props":170,"children":172},{"class":143,"line":171},2,[173,178,183,188,193,198,203],{"type":24,"tag":141,"props":174,"children":175},{"style":165},[176],{"type":34,"value":177},"  apiKey: ",{"type":24,"tag":141,"props":179,"children":180},{"style":148},[181],{"type":34,"value":182},"import",{"type":24,"tag":141,"props":184,"children":185},{"style":165},[186],{"type":34,"value":187},".",{"type":24,"tag":141,"props":189,"children":190},{"style":154},[191],{"type":34,"value":192},"meta",{"type":24,"tag":141,"props":194,"children":195},{"style":165},[196],{"type":34,"value":197},".env.",{"type":24,"tag":141,"props":199,"children":200},{"style":154},[201],{"type":34,"value":202},"VITE_APP_FIREBASE_API_KEY",{"type":24,"tag":141,"props":204,"children":205},{"style":165},[206],{"type":34,"value":207},",\n",{"type":24,"tag":141,"props":209,"children":211},{"class":143,"line":210},3,[212,217,221,225,229,233,238],{"type":24,"tag":141,"props":213,"children":214},{"style":165},[215],{"type":34,"value":216},"  authDomain: ",{"type":24,"tag":141,"props":218,"children":219},{"style":148},[220],{"type":34,"value":182},{"type":24,"tag":141,"props":222,"children":223},{"style":165},[224],{"type":34,"value":187},{"type":24,"tag":141,"props":226,"children":227},{"style":154},[228],{"type":34,"value":192},{"type":24,"tag":141,"props":230,"children":231},{"style":165},[232],{"type":34,"value":197},{"type":24,"tag":141,"props":234,"children":235},{"style":154},[236],{"type":34,"value":237},"VITE_APP_FIREABASE_AUTH_DOMAIN",{"type":24,"tag":141,"props":239,"children":240},{"style":165},[241],{"type":34,"value":207},{"type":24,"tag":141,"props":243,"children":245},{"class":143,"line":244},4,[246,251,255,259,263,267,272],{"type":24,"tag":141,"props":247,"children":248},{"style":165},[249],{"type":34,"value":250},"  databaseURL: ",{"type":24,"tag":141,"props":252,"children":253},{"style":148},[254],{"type":34,"value":182},{"type":24,"tag":141,"props":256,"children":257},{"style":165},[258],{"type":34,"value":187},{"type":24,"tag":141,"props":260,"children":261},{"style":154},[262],{"type":34,"value":192},{"type":24,"tag":141,"props":264,"children":265},{"style":165},[266],{"type":34,"value":197},{"type":24,"tag":141,"props":268,"children":269},{"style":154},[270],{"type":34,"value":271},"VITE_APP_FIREABASE_DATABASE_URL",{"type":24,"tag":141,"props":273,"children":274},{"style":165},[275],{"type":34,"value":207},{"type":24,"tag":141,"props":277,"children":279},{"class":143,"line":278},5,[280,285,289,293,297,301,306],{"type":24,"tag":141,"props":281,"children":282},{"style":165},[283],{"type":34,"value":284},"  projectId: ",{"type":24,"tag":141,"props":286,"children":287},{"style":148},[288],{"type":34,"value":182},{"type":24,"tag":141,"props":290,"children":291},{"style":165},[292],{"type":34,"value":187},{"type":24,"tag":141,"props":294,"children":295},{"style":154},[296],{"type":34,"value":192},{"type":24,"tag":141,"props":298,"children":299},{"style":165},[300],{"type":34,"value":197},{"type":24,"tag":141,"props":302,"children":303},{"style":154},[304],{"type":34,"value":305},"VITE_APP_PROJECT_ID",{"type":24,"tag":141,"props":307,"children":308},{"style":165},[309],{"type":34,"value":207},{"type":24,"tag":141,"props":311,"children":313},{"class":143,"line":312},6,[314,319,323,327,331,335,340],{"type":24,"tag":141,"props":315,"children":316},{"style":165},[317],{"type":34,"value":318},"  storageBucket: ",{"type":24,"tag":141,"props":320,"children":321},{"style":148},[322],{"type":34,"value":182},{"type":24,"tag":141,"props":324,"children":325},{"style":165},[326],{"type":34,"value":187},{"type":24,"tag":141,"props":328,"children":329},{"style":154},[330],{"type":34,"value":192},{"type":24,"tag":141,"props":332,"children":333},{"style":165},[334],{"type":34,"value":197},{"type":24,"tag":141,"props":336,"children":337},{"style":154},[338],{"type":34,"value":339},"VITE_APP_FIREBASE_STORAGE_BUCKET",{"type":24,"tag":141,"props":341,"children":342},{"style":165},[343],{"type":34,"value":207},{"type":24,"tag":141,"props":345,"children":347},{"class":143,"line":346},7,[348,353,357,361,365,369,374],{"type":24,"tag":141,"props":349,"children":350},{"style":165},[351],{"type":34,"value":352},"  messagingSenderId: ",{"type":24,"tag":141,"props":354,"children":355},{"style":148},[356],{"type":34,"value":182},{"type":24,"tag":141,"props":358,"children":359},{"style":165},[360],{"type":34,"value":187},{"type":24,"tag":141,"props":362,"children":363},{"style":154},[364],{"type":34,"value":192},{"type":24,"tag":141,"props":366,"children":367},{"style":165},[368],{"type":34,"value":197},{"type":24,"tag":141,"props":370,"children":371},{"style":154},[372],{"type":34,"value":373},"VITE_APP_FIREBASE_MESSAGING_SENDER_ID",{"type":24,"tag":141,"props":375,"children":376},{"style":165},[377],{"type":34,"value":207},{"type":24,"tag":141,"props":379,"children":381},{"class":143,"line":380},8,[382,387,391,395,399,403,408],{"type":24,"tag":141,"props":383,"children":384},{"style":165},[385],{"type":34,"value":386},"  appId: ",{"type":24,"tag":141,"props":388,"children":389},{"style":148},[390],{"type":34,"value":182},{"type":24,"tag":141,"props":392,"children":393},{"style":165},[394],{"type":34,"value":187},{"type":24,"tag":141,"props":396,"children":397},{"style":154},[398],{"type":34,"value":192},{"type":24,"tag":141,"props":400,"children":401},{"style":165},[402],{"type":34,"value":197},{"type":24,"tag":141,"props":404,"children":405},{"style":154},[406],{"type":34,"value":407},"VITE_APP_FIREBASE_APP_ID",{"type":24,"tag":141,"props":409,"children":410},{"style":165},[411],{"type":34,"value":207},{"type":24,"tag":141,"props":413,"children":415},{"class":143,"line":414},9,[416,421,425,429,433,437],{"type":24,"tag":141,"props":417,"children":418},{"style":165},[419],{"type":34,"value":420},"  measurementId: ",{"type":24,"tag":141,"props":422,"children":423},{"style":148},[424],{"type":34,"value":182},{"type":24,"tag":141,"props":426,"children":427},{"style":165},[428],{"type":34,"value":187},{"type":24,"tag":141,"props":430,"children":431},{"style":154},[432],{"type":34,"value":192},{"type":24,"tag":141,"props":434,"children":435},{"style":165},[436],{"type":34,"value":197},{"type":24,"tag":141,"props":438,"children":439},{"style":154},[440],{"type":34,"value":441},"VITE_APP_FIREBASE_MEASUREMENT_ID\n",{"type":24,"tag":141,"props":443,"children":445},{"class":143,"line":444},10,[446],{"type":24,"tag":141,"props":447,"children":448},{"style":165},[449],{"type":34,"value":450},"};\n",{"type":24,"tag":141,"props":452,"children":454},{"class":143,"line":453},11,[455,460,465],{"type":24,"tag":141,"props":456,"children":457},{"style":148},[458],{"type":34,"value":459},"export",{"type":24,"tag":141,"props":461,"children":462},{"style":148},[463],{"type":34,"value":464}," default",{"type":24,"tag":141,"props":466,"children":467},{"style":165},[468],{"type":34,"value":469}," firebaseConfig;\n",{"type":24,"tag":37,"props":471,"children":472},{},[473,475,481,483,489],{"type":34,"value":474},"The ",{"type":24,"tag":476,"props":477,"children":478},"em",{},[479],{"type":34,"value":480},"VAPKEY",{"type":34,"value":482}," is not included in the firebaseConfig object. You need to get it by generating ",{"type":24,"tag":116,"props":484,"children":486},{"className":485},[],[487],{"type":34,"value":488},"Web Push Certificates",{"type":34,"value":490}," pair for the Web Configuration under your firebase project -> Project settings -> Cloud Messaging",{"type":24,"tag":61,"props":492,"children":494},{"id":493},"using-the-repository",[495],{"type":34,"value":496},"Using the repository",{"type":24,"tag":37,"props":498,"children":499},{},[500,502,507],{"type":34,"value":501},"After you filled the ",{"type":24,"tag":116,"props":503,"children":505},{"className":504},[],[506],{"type":34,"value":107},{"type":34,"value":508}," file as per the template you can install the dependencies in the project and run it",{"type":24,"tag":68,"props":510,"children":511},{},[512,521],{"type":24,"tag":72,"props":513,"children":514},{},[515],{"type":24,"tag":116,"props":516,"children":518},{"className":517},[],[519],{"type":34,"value":520},"pnpm install",{"type":24,"tag":72,"props":522,"children":523},{},[524],{"type":24,"tag":116,"props":525,"children":527},{"className":526},[],[528],{"type":34,"value":529},"pnpm run dev",{"type":24,"tag":37,"props":531,"children":532},{},[533,535,540],{"type":34,"value":534},"Clicking the ",{"type":24,"tag":476,"props":536,"children":537},{},[538],{"type":34,"value":539},"Subscribe",{"type":34,"value":541}," button will print the token needed when sending notifications",{"type":24,"tag":61,"props":543,"children":545},{"id":544},"the-challenges",[546],{"type":34,"value":547},"The challenges",{"type":24,"tag":549,"props":550,"children":552},"h3",{"id":551},"firebase-service-worker",[553],{"type":34,"value":554},"Firebase service worker",{"type":24,"tag":37,"props":556,"children":557},{},[558],{"type":34,"value":559},"An important piece of the whole setup is the firebase-messaging-sw.js file. The service worker used by firebase.",{"type":24,"tag":37,"props":561,"children":562},{},[563],{"type":34,"value":564},"Normally you would just put into the public folder with all the credentials in it and then it will be loaded automatically. But because I like to struggle, i did it differently.",{"type":24,"tag":37,"props":566,"children":567},{},[568,570,575,577,583],{"type":34,"value":569},"I wanted all the credentials to be pulled from the ",{"type":24,"tag":116,"props":571,"children":573},{"className":572},[],[574],{"type":34,"value":107},{"type":34,"value":576}," file. With vite you grav them with ",{"type":24,"tag":116,"props":578,"children":580},{"className":579},[],[581],{"type":34,"value":582},"import.meta.env.VITE_APP_VAR",{"type":34,"value":187},{"type":24,"tag":37,"props":585,"children":586},{},[587],{"type":34,"value":588},"Issue with having the file in the public folder is that you will be limited to what you can import or use. So you need to do it differently",{"type":24,"tag":37,"props":590,"children":591},{},[592,597,599],{"type":24,"tag":476,"props":593,"children":594},{},[595],{"type":34,"value":596},"Solution",{"type":34,"value":598},": Manually registering the service worker with ",{"type":24,"tag":116,"props":600,"children":602},{"className":601},[],[603],{"type":34,"value":604},"{ type: \"module\" }",{"type":24,"tag":37,"props":606,"children":607},{},[608],{"type":34,"value":609},"This way you can keep it in your root/src folder and get it compiled. This way it get's properly processed by vite and everything is setup correctly.",{"type":24,"tag":111,"props":611,"children":613},{"code":612,"language":134,"meta":7,"className":135,"style":7},"// firebase-messaging-sw.js\nimport { initializeApp } from \"firebase/app\";\nimport { getMessaging } from \"firebase/messaging/sw\";\nimport { onBackgroundMessage } from \"firebase/messaging/sw\";\n\nimport config from \"./firebase.config.js\";\nconst app = initializeApp(config);\nconst messaging = getMessaging();\n\nonBackgroundMessage(messaging, (payload) => {\n  console.log(payload);\n  console.log(\n    \"[firebase-messaging-sw.js] Received background message \",\n    payload\n  );\n  // Customize notification here\n  const notificationTitle = \"Background Message Title\";\n  const notificationOptions = {\n    body: \"Background Message body.\",\n    icon: \"/vite.svg\"\n  };\n\n  self.registration.showNotification(notificationTitle, notificationOptions);\n});\n",[614],{"type":24,"tag":116,"props":615,"children":616},{"__ignoreMap":7},[617,626,654,679,703,712,737,764,790,797,830,848,865,878,887,896,905,932,953,971,985,994,1002,1021],{"type":24,"tag":141,"props":618,"children":619},{"class":143,"line":144},[620],{"type":24,"tag":141,"props":621,"children":623},{"style":622},"--shiki-default:#6A737D",[624],{"type":34,"value":625},"// firebase-messaging-sw.js\n",{"type":24,"tag":141,"props":627,"children":628},{"class":143,"line":171},[629,633,638,643,649],{"type":24,"tag":141,"props":630,"children":631},{"style":148},[632],{"type":34,"value":182},{"type":24,"tag":141,"props":634,"children":635},{"style":165},[636],{"type":34,"value":637}," { initializeApp } ",{"type":24,"tag":141,"props":639,"children":640},{"style":148},[641],{"type":34,"value":642},"from",{"type":24,"tag":141,"props":644,"children":646},{"style":645},"--shiki-default:#9ECBFF",[647],{"type":34,"value":648}," \"firebase/app\"",{"type":24,"tag":141,"props":650,"children":651},{"style":165},[652],{"type":34,"value":653},";\n",{"type":24,"tag":141,"props":655,"children":656},{"class":143,"line":210},[657,661,666,670,675],{"type":24,"tag":141,"props":658,"children":659},{"style":148},[660],{"type":34,"value":182},{"type":24,"tag":141,"props":662,"children":663},{"style":165},[664],{"type":34,"value":665}," { getMessaging } ",{"type":24,"tag":141,"props":667,"children":668},{"style":148},[669],{"type":34,"value":642},{"type":24,"tag":141,"props":671,"children":672},{"style":645},[673],{"type":34,"value":674}," \"firebase/messaging/sw\"",{"type":24,"tag":141,"props":676,"children":677},{"style":165},[678],{"type":34,"value":653},{"type":24,"tag":141,"props":680,"children":681},{"class":143,"line":244},[682,686,691,695,699],{"type":24,"tag":141,"props":683,"children":684},{"style":148},[685],{"type":34,"value":182},{"type":24,"tag":141,"props":687,"children":688},{"style":165},[689],{"type":34,"value":690}," { onBackgroundMessage } ",{"type":24,"tag":141,"props":692,"children":693},{"style":148},[694],{"type":34,"value":642},{"type":24,"tag":141,"props":696,"children":697},{"style":645},[698],{"type":34,"value":674},{"type":24,"tag":141,"props":700,"children":701},{"style":165},[702],{"type":34,"value":653},{"type":24,"tag":141,"props":704,"children":705},{"class":143,"line":278},[706],{"type":24,"tag":141,"props":707,"children":709},{"emptyLinePlaceholder":708},true,[710],{"type":34,"value":711},"\n",{"type":24,"tag":141,"props":713,"children":714},{"class":143,"line":312},[715,719,724,728,733],{"type":24,"tag":141,"props":716,"children":717},{"style":148},[718],{"type":34,"value":182},{"type":24,"tag":141,"props":720,"children":721},{"style":165},[722],{"type":34,"value":723}," config ",{"type":24,"tag":141,"props":725,"children":726},{"style":148},[727],{"type":34,"value":642},{"type":24,"tag":141,"props":729,"children":730},{"style":645},[731],{"type":34,"value":732}," \"./firebase.config.js\"",{"type":24,"tag":141,"props":734,"children":735},{"style":165},[736],{"type":34,"value":653},{"type":24,"tag":141,"props":738,"children":739},{"class":143,"line":346},[740,744,749,753,759],{"type":24,"tag":141,"props":741,"children":742},{"style":148},[743],{"type":34,"value":151},{"type":24,"tag":141,"props":745,"children":746},{"style":154},[747],{"type":34,"value":748}," app",{"type":24,"tag":141,"props":750,"children":751},{"style":148},[752],{"type":34,"value":162},{"type":24,"tag":141,"props":754,"children":756},{"style":755},"--shiki-default:#B392F0",[757],{"type":34,"value":758}," initializeApp",{"type":24,"tag":141,"props":760,"children":761},{"style":165},[762],{"type":34,"value":763},"(config);\n",{"type":24,"tag":141,"props":765,"children":766},{"class":143,"line":380},[767,771,776,780,785],{"type":24,"tag":141,"props":768,"children":769},{"style":148},[770],{"type":34,"value":151},{"type":24,"tag":141,"props":772,"children":773},{"style":154},[774],{"type":34,"value":775}," messaging",{"type":24,"tag":141,"props":777,"children":778},{"style":148},[779],{"type":34,"value":162},{"type":24,"tag":141,"props":781,"children":782},{"style":755},[783],{"type":34,"value":784}," getMessaging",{"type":24,"tag":141,"props":786,"children":787},{"style":165},[788],{"type":34,"value":789},"();\n",{"type":24,"tag":141,"props":791,"children":792},{"class":143,"line":414},[793],{"type":24,"tag":141,"props":794,"children":795},{"emptyLinePlaceholder":708},[796],{"type":34,"value":711},{"type":24,"tag":141,"props":798,"children":799},{"class":143,"line":444},[800,805,810,816,821,826],{"type":24,"tag":141,"props":801,"children":802},{"style":755},[803],{"type":34,"value":804},"onBackgroundMessage",{"type":24,"tag":141,"props":806,"children":807},{"style":165},[808],{"type":34,"value":809},"(messaging, (",{"type":24,"tag":141,"props":811,"children":813},{"style":812},"--shiki-default:#FFAB70",[814],{"type":34,"value":815},"payload",{"type":24,"tag":141,"props":817,"children":818},{"style":165},[819],{"type":34,"value":820},") ",{"type":24,"tag":141,"props":822,"children":823},{"style":148},[824],{"type":34,"value":825},"=>",{"type":24,"tag":141,"props":827,"children":828},{"style":165},[829],{"type":34,"value":168},{"type":24,"tag":141,"props":831,"children":832},{"class":143,"line":453},[833,838,843],{"type":24,"tag":141,"props":834,"children":835},{"style":165},[836],{"type":34,"value":837},"  console.",{"type":24,"tag":141,"props":839,"children":840},{"style":755},[841],{"type":34,"value":842},"log",{"type":24,"tag":141,"props":844,"children":845},{"style":165},[846],{"type":34,"value":847},"(payload);\n",{"type":24,"tag":141,"props":849,"children":851},{"class":143,"line":850},12,[852,856,860],{"type":24,"tag":141,"props":853,"children":854},{"style":165},[855],{"type":34,"value":837},{"type":24,"tag":141,"props":857,"children":858},{"style":755},[859],{"type":34,"value":842},{"type":24,"tag":141,"props":861,"children":862},{"style":165},[863],{"type":34,"value":864},"(\n",{"type":24,"tag":141,"props":866,"children":868},{"class":143,"line":867},13,[869,874],{"type":24,"tag":141,"props":870,"children":871},{"style":645},[872],{"type":34,"value":873},"    \"[firebase-messaging-sw.js] Received background message \"",{"type":24,"tag":141,"props":875,"children":876},{"style":165},[877],{"type":34,"value":207},{"type":24,"tag":141,"props":879,"children":881},{"class":143,"line":880},14,[882],{"type":24,"tag":141,"props":883,"children":884},{"style":165},[885],{"type":34,"value":886},"    payload\n",{"type":24,"tag":141,"props":888,"children":890},{"class":143,"line":889},15,[891],{"type":24,"tag":141,"props":892,"children":893},{"style":165},[894],{"type":34,"value":895},"  );\n",{"type":24,"tag":141,"props":897,"children":899},{"class":143,"line":898},16,[900],{"type":24,"tag":141,"props":901,"children":902},{"style":622},[903],{"type":34,"value":904},"  // Customize notification here\n",{"type":24,"tag":141,"props":906,"children":908},{"class":143,"line":907},17,[909,914,919,923,928],{"type":24,"tag":141,"props":910,"children":911},{"style":148},[912],{"type":34,"value":913},"  const",{"type":24,"tag":141,"props":915,"children":916},{"style":154},[917],{"type":34,"value":918}," notificationTitle",{"type":24,"tag":141,"props":920,"children":921},{"style":148},[922],{"type":34,"value":162},{"type":24,"tag":141,"props":924,"children":925},{"style":645},[926],{"type":34,"value":927}," \"Background Message Title\"",{"type":24,"tag":141,"props":929,"children":930},{"style":165},[931],{"type":34,"value":653},{"type":24,"tag":141,"props":933,"children":935},{"class":143,"line":934},18,[936,940,945,949],{"type":24,"tag":141,"props":937,"children":938},{"style":148},[939],{"type":34,"value":913},{"type":24,"tag":141,"props":941,"children":942},{"style":154},[943],{"type":34,"value":944}," notificationOptions",{"type":24,"tag":141,"props":946,"children":947},{"style":148},[948],{"type":34,"value":162},{"type":24,"tag":141,"props":950,"children":951},{"style":165},[952],{"type":34,"value":168},{"type":24,"tag":141,"props":954,"children":956},{"class":143,"line":955},19,[957,962,967],{"type":24,"tag":141,"props":958,"children":959},{"style":165},[960],{"type":34,"value":961},"    body: ",{"type":24,"tag":141,"props":963,"children":964},{"style":645},[965],{"type":34,"value":966},"\"Background Message body.\"",{"type":24,"tag":141,"props":968,"children":969},{"style":165},[970],{"type":34,"value":207},{"type":24,"tag":141,"props":972,"children":974},{"class":143,"line":973},20,[975,980],{"type":24,"tag":141,"props":976,"children":977},{"style":165},[978],{"type":34,"value":979},"    icon: ",{"type":24,"tag":141,"props":981,"children":982},{"style":645},[983],{"type":34,"value":984},"\"/vite.svg\"\n",{"type":24,"tag":141,"props":986,"children":988},{"class":143,"line":987},21,[989],{"type":24,"tag":141,"props":990,"children":991},{"style":165},[992],{"type":34,"value":993},"  };\n",{"type":24,"tag":141,"props":995,"children":997},{"class":143,"line":996},22,[998],{"type":24,"tag":141,"props":999,"children":1000},{"emptyLinePlaceholder":708},[1001],{"type":34,"value":711},{"type":24,"tag":141,"props":1003,"children":1005},{"class":143,"line":1004},23,[1006,1011,1016],{"type":24,"tag":141,"props":1007,"children":1008},{"style":165},[1009],{"type":34,"value":1010},"  self.registration.",{"type":24,"tag":141,"props":1012,"children":1013},{"style":755},[1014],{"type":34,"value":1015},"showNotification",{"type":24,"tag":141,"props":1017,"children":1018},{"style":165},[1019],{"type":34,"value":1020},"(notificationTitle, notificationOptions);\n",{"type":24,"tag":141,"props":1022,"children":1024},{"class":143,"line":1023},24,[1025],{"type":24,"tag":141,"props":1026,"children":1027},{"style":165},[1028],{"type":34,"value":1029},"});\n",{"type":24,"tag":37,"props":1031,"children":1032},{},[1033],{"type":34,"value":1034},"To register the service worker you just need to do this",{"type":24,"tag":111,"props":1036,"children":1038},{"code":1037,"language":134,"meta":7,"className":135,"style":7},"const registration = await navigator.serviceWorker.register(\n  \"./firebase-messaging-sw.js\",\n  {\n    type: \"module\"\n  }\n);\n",[1039],{"type":24,"tag":116,"props":1040,"children":1041},{"__ignoreMap":7},[1042,1077,1089,1097,1110,1118],{"type":24,"tag":141,"props":1043,"children":1044},{"class":143,"line":144},[1045,1049,1054,1058,1063,1068,1073],{"type":24,"tag":141,"props":1046,"children":1047},{"style":148},[1048],{"type":34,"value":151},{"type":24,"tag":141,"props":1050,"children":1051},{"style":154},[1052],{"type":34,"value":1053}," registration",{"type":24,"tag":141,"props":1055,"children":1056},{"style":148},[1057],{"type":34,"value":162},{"type":24,"tag":141,"props":1059,"children":1060},{"style":148},[1061],{"type":34,"value":1062}," await",{"type":24,"tag":141,"props":1064,"children":1065},{"style":165},[1066],{"type":34,"value":1067}," navigator.serviceWorker.",{"type":24,"tag":141,"props":1069,"children":1070},{"style":755},[1071],{"type":34,"value":1072},"register",{"type":24,"tag":141,"props":1074,"children":1075},{"style":165},[1076],{"type":34,"value":864},{"type":24,"tag":141,"props":1078,"children":1079},{"class":143,"line":171},[1080,1085],{"type":24,"tag":141,"props":1081,"children":1082},{"style":645},[1083],{"type":34,"value":1084},"  \"./firebase-messaging-sw.js\"",{"type":24,"tag":141,"props":1086,"children":1087},{"style":165},[1088],{"type":34,"value":207},{"type":24,"tag":141,"props":1090,"children":1091},{"class":143,"line":210},[1092],{"type":24,"tag":141,"props":1093,"children":1094},{"style":165},[1095],{"type":34,"value":1096},"  {\n",{"type":24,"tag":141,"props":1098,"children":1099},{"class":143,"line":244},[1100,1105],{"type":24,"tag":141,"props":1101,"children":1102},{"style":165},[1103],{"type":34,"value":1104},"    type: ",{"type":24,"tag":141,"props":1106,"children":1107},{"style":645},[1108],{"type":34,"value":1109},"\"module\"\n",{"type":24,"tag":141,"props":1111,"children":1112},{"class":143,"line":278},[1113],{"type":24,"tag":141,"props":1114,"children":1115},{"style":165},[1116],{"type":34,"value":1117},"  }\n",{"type":24,"tag":141,"props":1119,"children":1120},{"class":143,"line":312},[1121],{"type":24,"tag":141,"props":1122,"children":1123},{"style":165},[1124],{"type":34,"value":1125},");\n",{"type":24,"tag":37,"props":1127,"children":1128},{},[1129,1131,1136,1138,1143,1145],{"type":34,"value":1130},"Make sure you keep track of the ",{"type":24,"tag":476,"props":1132,"children":1133},{},[1134],{"type":34,"value":1135},"registration",{"type":34,"value":1137}," as this needs to be used when calling the ",{"type":24,"tag":476,"props":1139,"children":1140},{},[1141],{"type":34,"value":1142},"getToken",{"type":34,"value":1144}," method. I'm using a class for all the firebase interaction ",{"type":24,"tag":41,"props":1146,"children":1149},{"href":1147,"rel":1148},"https://github.com/andreitere/firebase-web-notifications/blob/main/notifications.js",[45],[1150],{"type":34,"value":1151},"notifications.js",{"type":24,"tag":549,"props":1153,"children":1155},{"id":1154},"building-for-production",[1156],{"type":34,"value":1157},"Building for production",{"type":24,"tag":37,"props":1159,"children":1160},{},[1161,1163,1169],{"type":34,"value":1162},"The service worker we currently have in the root folder ",{"type":24,"tag":116,"props":1164,"children":1166},{"className":1165},[],[1167],{"type":34,"value":1168},"firebase-messaging-sw.js",{"type":34,"value":1170}," is not imported anywhere so vite will ignore it on build.",{"type":24,"tag":37,"props":1172,"children":1173},{},[1174],{"type":34,"value":1175},"What we need to do it a custom build config for it so that it will get outputed in the dist folder.",{"type":24,"tag":37,"props":1177,"children":1178},{},[1179,1181],{"type":34,"value":1180},"Quite straightforward I would say. In vite.config.js I'm using a custom config based on the VITE_CONFIG so that first i'm building the ",{"type":24,"tag":116,"props":1182,"children":1184},{"className":1183},[],[1185],{"type":34,"value":1168},{"type":24,"tag":111,"props":1187,"children":1189},{"code":1188,"language":134,"meta":7,"className":135,"style":7},"import { defineConfig } from \"vite\";\n\nconst configs = {\n  sw: {\n    build: {\n      outdir: \"./dist\",\n      lib: {\n        entry: resolve(\"./firebase-messaging-sw.js\"),\n        fileName: \"firebase-messaging-sw\",\n        formats: [\"es\"]\n      },\n      emptyOutDir: false\n    }\n  },\n  main: {}\n};\n\nconst config = configs[process.env.VITE_CONFIG];\nexport default defineConfig({\n  ...(config || {})\n});\n",[1190],{"type":24,"tag":116,"props":1191,"children":1192},{"__ignoreMap":7},[1193,1218,1225,1245,1253,1261,1278,1286,1314,1331,1349,1357,1370,1378,1386,1394,1401,1408,1439,1460,1483],{"type":24,"tag":141,"props":1194,"children":1195},{"class":143,"line":144},[1196,1200,1205,1209,1214],{"type":24,"tag":141,"props":1197,"children":1198},{"style":148},[1199],{"type":34,"value":182},{"type":24,"tag":141,"props":1201,"children":1202},{"style":165},[1203],{"type":34,"value":1204}," { defineConfig } ",{"type":24,"tag":141,"props":1206,"children":1207},{"style":148},[1208],{"type":34,"value":642},{"type":24,"tag":141,"props":1210,"children":1211},{"style":645},[1212],{"type":34,"value":1213}," \"vite\"",{"type":24,"tag":141,"props":1215,"children":1216},{"style":165},[1217],{"type":34,"value":653},{"type":24,"tag":141,"props":1219,"children":1220},{"class":143,"line":171},[1221],{"type":24,"tag":141,"props":1222,"children":1223},{"emptyLinePlaceholder":708},[1224],{"type":34,"value":711},{"type":24,"tag":141,"props":1226,"children":1227},{"class":143,"line":210},[1228,1232,1237,1241],{"type":24,"tag":141,"props":1229,"children":1230},{"style":148},[1231],{"type":34,"value":151},{"type":24,"tag":141,"props":1233,"children":1234},{"style":154},[1235],{"type":34,"value":1236}," configs",{"type":24,"tag":141,"props":1238,"children":1239},{"style":148},[1240],{"type":34,"value":162},{"type":24,"tag":141,"props":1242,"children":1243},{"style":165},[1244],{"type":34,"value":168},{"type":24,"tag":141,"props":1246,"children":1247},{"class":143,"line":244},[1248],{"type":24,"tag":141,"props":1249,"children":1250},{"style":165},[1251],{"type":34,"value":1252},"  sw: {\n",{"type":24,"tag":141,"props":1254,"children":1255},{"class":143,"line":278},[1256],{"type":24,"tag":141,"props":1257,"children":1258},{"style":165},[1259],{"type":34,"value":1260},"    build: {\n",{"type":24,"tag":141,"props":1262,"children":1263},{"class":143,"line":312},[1264,1269,1274],{"type":24,"tag":141,"props":1265,"children":1266},{"style":165},[1267],{"type":34,"value":1268},"      outdir: ",{"type":24,"tag":141,"props":1270,"children":1271},{"style":645},[1272],{"type":34,"value":1273},"\"./dist\"",{"type":24,"tag":141,"props":1275,"children":1276},{"style":165},[1277],{"type":34,"value":207},{"type":24,"tag":141,"props":1279,"children":1280},{"class":143,"line":346},[1281],{"type":24,"tag":141,"props":1282,"children":1283},{"style":165},[1284],{"type":34,"value":1285},"      lib: {\n",{"type":24,"tag":141,"props":1287,"children":1288},{"class":143,"line":380},[1289,1294,1299,1304,1309],{"type":24,"tag":141,"props":1290,"children":1291},{"style":165},[1292],{"type":34,"value":1293},"        entry: ",{"type":24,"tag":141,"props":1295,"children":1296},{"style":755},[1297],{"type":34,"value":1298},"resolve",{"type":24,"tag":141,"props":1300,"children":1301},{"style":165},[1302],{"type":34,"value":1303},"(",{"type":24,"tag":141,"props":1305,"children":1306},{"style":645},[1307],{"type":34,"value":1308},"\"./firebase-messaging-sw.js\"",{"type":24,"tag":141,"props":1310,"children":1311},{"style":165},[1312],{"type":34,"value":1313},"),\n",{"type":24,"tag":141,"props":1315,"children":1316},{"class":143,"line":414},[1317,1322,1327],{"type":24,"tag":141,"props":1318,"children":1319},{"style":165},[1320],{"type":34,"value":1321},"        fileName: ",{"type":24,"tag":141,"props":1323,"children":1324},{"style":645},[1325],{"type":34,"value":1326},"\"firebase-messaging-sw\"",{"type":24,"tag":141,"props":1328,"children":1329},{"style":165},[1330],{"type":34,"value":207},{"type":24,"tag":141,"props":1332,"children":1333},{"class":143,"line":444},[1334,1339,1344],{"type":24,"tag":141,"props":1335,"children":1336},{"style":165},[1337],{"type":34,"value":1338},"        formats: [",{"type":24,"tag":141,"props":1340,"children":1341},{"style":645},[1342],{"type":34,"value":1343},"\"es\"",{"type":24,"tag":141,"props":1345,"children":1346},{"style":165},[1347],{"type":34,"value":1348},"]\n",{"type":24,"tag":141,"props":1350,"children":1351},{"class":143,"line":453},[1352],{"type":24,"tag":141,"props":1353,"children":1354},{"style":165},[1355],{"type":34,"value":1356},"      },\n",{"type":24,"tag":141,"props":1358,"children":1359},{"class":143,"line":850},[1360,1365],{"type":24,"tag":141,"props":1361,"children":1362},{"style":165},[1363],{"type":34,"value":1364},"      emptyOutDir: ",{"type":24,"tag":141,"props":1366,"children":1367},{"style":154},[1368],{"type":34,"value":1369},"false\n",{"type":24,"tag":141,"props":1371,"children":1372},{"class":143,"line":867},[1373],{"type":24,"tag":141,"props":1374,"children":1375},{"style":165},[1376],{"type":34,"value":1377},"    }\n",{"type":24,"tag":141,"props":1379,"children":1380},{"class":143,"line":880},[1381],{"type":24,"tag":141,"props":1382,"children":1383},{"style":165},[1384],{"type":34,"value":1385},"  },\n",{"type":24,"tag":141,"props":1387,"children":1388},{"class":143,"line":889},[1389],{"type":24,"tag":141,"props":1390,"children":1391},{"style":165},[1392],{"type":34,"value":1393},"  main: {}\n",{"type":24,"tag":141,"props":1395,"children":1396},{"class":143,"line":898},[1397],{"type":24,"tag":141,"props":1398,"children":1399},{"style":165},[1400],{"type":34,"value":450},{"type":24,"tag":141,"props":1402,"children":1403},{"class":143,"line":907},[1404],{"type":24,"tag":141,"props":1405,"children":1406},{"emptyLinePlaceholder":708},[1407],{"type":34,"value":711},{"type":24,"tag":141,"props":1409,"children":1410},{"class":143,"line":934},[1411,1415,1420,1424,1429,1434],{"type":24,"tag":141,"props":1412,"children":1413},{"style":148},[1414],{"type":34,"value":151},{"type":24,"tag":141,"props":1416,"children":1417},{"style":154},[1418],{"type":34,"value":1419}," config",{"type":24,"tag":141,"props":1421,"children":1422},{"style":148},[1423],{"type":34,"value":162},{"type":24,"tag":141,"props":1425,"children":1426},{"style":165},[1427],{"type":34,"value":1428}," configs[process.env.",{"type":24,"tag":141,"props":1430,"children":1431},{"style":154},[1432],{"type":34,"value":1433},"VITE_CONFIG",{"type":24,"tag":141,"props":1435,"children":1436},{"style":165},[1437],{"type":34,"value":1438},"];\n",{"type":24,"tag":141,"props":1440,"children":1441},{"class":143,"line":955},[1442,1446,1450,1455],{"type":24,"tag":141,"props":1443,"children":1444},{"style":148},[1445],{"type":34,"value":459},{"type":24,"tag":141,"props":1447,"children":1448},{"style":148},[1449],{"type":34,"value":464},{"type":24,"tag":141,"props":1451,"children":1452},{"style":755},[1453],{"type":34,"value":1454}," defineConfig",{"type":24,"tag":141,"props":1456,"children":1457},{"style":165},[1458],{"type":34,"value":1459},"({\n",{"type":24,"tag":141,"props":1461,"children":1462},{"class":143,"line":973},[1463,1468,1473,1478],{"type":24,"tag":141,"props":1464,"children":1465},{"style":148},[1466],{"type":34,"value":1467},"  ...",{"type":24,"tag":141,"props":1469,"children":1470},{"style":165},[1471],{"type":34,"value":1472},"(config ",{"type":24,"tag":141,"props":1474,"children":1475},{"style":148},[1476],{"type":34,"value":1477},"||",{"type":24,"tag":141,"props":1479,"children":1480},{"style":165},[1481],{"type":34,"value":1482}," {})\n",{"type":24,"tag":141,"props":1484,"children":1485},{"class":143,"line":987},[1486],{"type":24,"tag":141,"props":1487,"children":1488},{"style":165},[1489],{"type":34,"value":1029},{"type":24,"tag":37,"props":1491,"children":1492},{},[1493,1495],{"type":34,"value":1494},"and the build commands from ",{"type":24,"tag":116,"props":1496,"children":1498},{"className":1497},[],[1499],{"type":34,"value":1500},"package.json",{"type":24,"tag":111,"props":1502,"children":1506},{"code":1503,"language":1504,"meta":7,"className":1505,"style":7},"{\n  \"build\": \"VITE_CONFIG=main vite build && VITE_CONFIG=sw vite build\",\n  \"build:sw\": \"VITE_CONFIG=sw vite build\",\n  \"build:site\": \"VITE_CONFIG=main vite build\"\n}\n","json","language-json shiki shiki-themes github-dark",[1507],{"type":24,"tag":116,"props":1508,"children":1509},{"__ignoreMap":7},[1510,1518,1540,1561,1578],{"type":24,"tag":141,"props":1511,"children":1512},{"class":143,"line":144},[1513],{"type":24,"tag":141,"props":1514,"children":1515},{"style":165},[1516],{"type":34,"value":1517},"{\n",{"type":24,"tag":141,"props":1519,"children":1520},{"class":143,"line":171},[1521,1526,1531,1536],{"type":24,"tag":141,"props":1522,"children":1523},{"style":154},[1524],{"type":34,"value":1525},"  \"build\"",{"type":24,"tag":141,"props":1527,"children":1528},{"style":165},[1529],{"type":34,"value":1530},": ",{"type":24,"tag":141,"props":1532,"children":1533},{"style":645},[1534],{"type":34,"value":1535},"\"VITE_CONFIG=main vite build && VITE_CONFIG=sw vite build\"",{"type":24,"tag":141,"props":1537,"children":1538},{"style":165},[1539],{"type":34,"value":207},{"type":24,"tag":141,"props":1541,"children":1542},{"class":143,"line":210},[1543,1548,1552,1557],{"type":24,"tag":141,"props":1544,"children":1545},{"style":154},[1546],{"type":34,"value":1547},"  \"build:sw\"",{"type":24,"tag":141,"props":1549,"children":1550},{"style":165},[1551],{"type":34,"value":1530},{"type":24,"tag":141,"props":1553,"children":1554},{"style":645},[1555],{"type":34,"value":1556},"\"VITE_CONFIG=sw vite build\"",{"type":24,"tag":141,"props":1558,"children":1559},{"style":165},[1560],{"type":34,"value":207},{"type":24,"tag":141,"props":1562,"children":1563},{"class":143,"line":244},[1564,1569,1573],{"type":24,"tag":141,"props":1565,"children":1566},{"style":154},[1567],{"type":34,"value":1568},"  \"build:site\"",{"type":24,"tag":141,"props":1570,"children":1571},{"style":165},[1572],{"type":34,"value":1530},{"type":24,"tag":141,"props":1574,"children":1575},{"style":645},[1576],{"type":34,"value":1577},"\"VITE_CONFIG=main vite build\"\n",{"type":24,"tag":141,"props":1579,"children":1580},{"class":143,"line":278},[1581],{"type":24,"tag":141,"props":1582,"children":1583},{"style":165},[1584],{"type":34,"value":1585},"}\n",{"type":24,"tag":37,"props":1587,"children":1588},{},[1589,1591,1597],{"type":34,"value":1590},"in the end, running ",{"type":24,"tag":116,"props":1592,"children":1594},{"className":1593},[],[1595],{"type":34,"value":1596},"pnpm run build",{"type":34,"value":1598}," will output all the required files.",{"type":24,"tag":549,"props":1600,"children":1602},{"id":1601},"sending-the-notification",[1603],{"type":34,"value":1604},"Sending the notification",{"type":24,"tag":37,"props":1606,"children":1607},{},[1608],{"type":34,"value":1609},"If when navigating to the main page won't display the token click on subscribe. You will be requested for Notifications permissions. Pay attention in case the browser is dening them by default. You will have to reset that.",{"type":24,"tag":37,"props":1611,"children":1612},{},[1613,1615,1621],{"type":34,"value":1614},"Grab the token, go to firebase console -> your project -> Messaging and compose a notification. Click on ",{"type":24,"tag":116,"props":1616,"children":1618},{"className":1617},[],[1619],{"type":34,"value":1620},"send test message",{"type":34,"value":1622}," and use the token you got after subscribing.",{"type":24,"tag":1624,"props":1625,"children":1626},"style",{},[1627],{"type":34,"value":1628},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":7,"searchDepth":171,"depth":171,"links":1630},[1631,1632,1633],{"id":63,"depth":171,"text":66},{"id":493,"depth":171,"text":496},{"id":544,"depth":171,"text":547,"children":1634},[1635,1636,1637],{"id":551,"depth":210,"text":554},{"id":1154,"depth":210,"text":1157},{"id":1601,"depth":210,"text":1604},"markdown","content:blog:4.firebase-web-notifications-tutorial-2023.md","content","blog/4.firebase-web-notifications-tutorial-2023.md","blog/4.firebase-web-notifications-tutorial-2023","md",1724422646760]