enuchi / React-Google-Apps-Script

This is your boilerplate project for developing React apps inside Google Sheets, Docs, Forms and Slides projects. It's perfect for personal projects and for publishing complex add-ons in the Google Workspace Marketplace.
MIT License
1.32k stars 172 forks source link

Issue with template literals containing // or /* #157

Open punkch opened 1 year ago

punkch commented 1 year ago

This is not an issue with this project, but rather than an Apps Script issue. Long story short, if you are using template literals, and they contain symbols for comments, google will strip these at the time of rendering., ie, if building an url or something, everything after the // will be removed and break the code.

MRE:

const onOpen = (e) => {
  DocumentApp.getUi() // Or SpreadsheetApp or SlidesApp or FormApp.
      .createMenu('Broken Dialog')
      .addItem('Open', 'openDialog')
      .addToUi();
}

const openDialog = () => {
  let markup = "<script>\n"
  markup += "document.write('<h1>');\n"
  markup += "document.write(`Apps Script is /*`);\n"
  markup += "document.write(`fun and never*/ broken`);\n"
  // this will throw an error in the console that is very hard to troubleshoot.
  // markup += "document.write(`// sometimes`);\n"
  markup += "document.write('</h1>');\n"
  markup += "</script>\n"

  const html = HtmlService.createHtmlOutput(markup)
    .setWidth(800)
    .setHeight(600);

  DocumentApp.getUi() // Or DocumentApp or SlidesApp or FormApp.
      .showModalDialog(html, 'Dialog title');
}

In my case, the issue was with firebase/auth, so I had to modify the webpack config to use babel-loader and add the '@babel/plugin-transform-template-literals' for all client js files. Something like:

const clientConfig = ({ isDevClientWrapper }) => ({
  ...sharedClientAndServerConfig,
  mode: isProd ? 'production' : 'development',
  output: {
    path: destination,
    // this file will get added to the html template inline
    // and should be put in .claspignore so it is not pushed
    filename: 'main.js',
    publicPath,
  },
  resolve: {
    extensions: ['.ts', '.tsx', '.js', '.jsx', '.json'],
  },
  module: {
    rules: [
      {
        test: /\.m?js/,
        resolve: {
          fullySpecified: false,
        },
        use: [
          {
            loader: 'babel-loader',
            options: {
              compact: false,
              plugins: [
                '@babel/plugin-transform-template-literals',
                !isProd &&
                  !isDevClientWrapper &&
                  require.resolve('react-refresh/babel'),
              ].filter(Boolean),
            },
          },
        ]
      },

I am not very experienced with babel and webpack, so not sure if this is the best way to do it, but it worked.

enuchi commented 1 year ago

Hmm that's a weird one. Haven't had a chance to test out but does it work if you just add '@babel/plugin-transform-template-literals' to the client .babelrc config file?

https://github.com/enuchi/React-Google-Apps-Script/blob/main/src/client/.babelrc

punkch commented 1 year ago

I've put it there too, but it was not doing it for my third party dependencies (node_modules).

glenne commented 1 year ago

@punkch I'm here looking at your solution wondering if it'll help me. Have you been able to successfully utilize firebase in your solution?

I'm trying to use firebase in my customization but my ui comes up blank when I add a call to initializeApp() with no warnings anywhere. Are you using the V9 modular API? How does it fail for you without this 'fix'?

punkch commented 1 year ago

Hi @glenne, yes I am using the v9 modular API and it fails in exactly the same way without this 'fix'. It works great during local development though.

glenne commented 1 year ago

Thanks @punkch ! I can verify that adding to .babelrc had no effect but the webpack.config.js modification worked for me in both production and dev. I did not add the compact:false line and it still worked for me.

BTW, how did you figure this out in the first place? For me it just silently failed so no clue what was happening.

punkch commented 1 year ago

Hi @glenne I don't remember exactly, but from a top of my head the compact:false was needed to improve babel performance when importing third party dependencies resulting in too much css in js. I am a bit offline at the moment and can't check what it was exactly. In order to figure was going on, I was doing non minified js builds while downgrading dependencies one by one. Then after two days of wtf it finally spat an error in the dev tools console with firebase 9.0.1 😭 I have in issue opened with Google and they are investigating. Will write here if/when I hear from them.

Zeyuzhao commented 1 year ago

I just want to follow up - the fix described in @punkch's web pack didn't work for me. I couldn't fix the error described. I am also trying to use firebase/auth in a modal, but an empty modal error persists. Could someone create a branch with a reproducible fix? Thanks!