Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(core): allow configureWebpack to return undefined #6784

Merged
merged 5 commits into from
Mar 22, 2022

Conversation

yorkie
Copy link
Contributor

@yorkie yorkie commented Feb 28, 2022

Motivation

() => {
  return {
    name: 'configure-server-side-rendering',
    configureWebpack(_, isServer) {
      if (isServer) {
        return {
          plugins: [
            new webpack.ProvidePlugin({
              'URLSearchParams': ['url', 'URLSearchParams'],
            }),
          ],
        }
      } else {
        return {};
      }
    },
  };
}

The above is a custom plugin to add a ProvidePlugin for server-side only, in this case, we don't wanna change the config for the client, but I have to return an empty object, so this PR is to improve the writing plugins in this case.

Have you read the Contributing Guidelines on pull requests?

Yes, and I will follow the commit guideline if this change LGTY :)

Test Plan

I'm not sure how to test this :)

Related PRs

None.

@facebook-github-bot facebook-github-bot added the CLA Signed Signed Facebook CLA label Feb 28, 2022
@netlify
Copy link

netlify bot commented Feb 28, 2022

✅ [V2]
Built without sensitive environment variables

🔨 Explore the source changes: 85d47f6

🔍 Inspect the deploy log: https://app.netlify.com/sites/docusaurus-2/deploys/623945a3226bbc0008a558ab

😎 Browse the preview: https://deploy-preview-6784--docusaurus-2.netlify.app

@github-actions
Copy link

github-actions bot commented Feb 28, 2022

⚡️ Lighthouse report for the changes in this PR:

Category Score
🟠 Performance 60
🟢 Accessibility 100
🟢 Best practices 92
🟢 SEO 100
🟢 PWA 90

Lighthouse ran on https://deploy-preview-6784--docusaurus-2.netlify.app/

@Josh-Cena Josh-Cena changed the title plugin: not acquire configureWebpack to return fix(core): allow configureWebpack to return undefined Feb 28, 2022
@Josh-Cena Josh-Cena added the pr: polish This PR adds a very minor behavior improvement that users will enjoy. label Feb 28, 2022
Copy link
Collaborator

@Josh-Cena Josh-Cena left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really like this change. It is good practice in JS to ensure symmetric return, and ESLint has a rule (consistent-return) to enforce this. Relying on the implicit undefined return may be the source of errors and is generally a code smell. Docusaurus wants to promote good coding practices.

Still I would leave the final decision to @slorber

@slorber
Copy link
Collaborator

slorber commented Mar 2, 2022

[ERROR] TypeError: Cannot destructure property 'mergeStrategy' of 'configureWebpack(...)' as it is undefined.

In any case, we want a better error message than the existing one:

Relying on the implicit undefined return may be the source of errors and is generally a code smell.

I think allowing the code above is quite convenient. Users can also explicitly return undefined.

Eventually we can force TS users to be more explicit:

  configureWebpack?: (
    config: Configuration,
    isServer: boolean,
    utils: ConfigureWebpackUtils,
    content: Content,
-  ) => Configuration & {mergeStrategy?: ConfigureWebpackFnMergeStrategy};
+  ) => (Configuration & {mergeStrategy?: ConfigureWebpackFnMergeStrategy}) | null;

JS users may still use implicit undefined and we can fail-safe in this case, or at least throw a better error message asking to return "null" explicitly?


@yorkie I'm willing to merge this change but I'd like to have a test + a correct TS type

Let us know if you want help

@Josh-Cena
Copy link
Collaborator

Josh-Cena commented Mar 2, 2022

No, the point is that this is succinct:

configureWebpack(isServer) {
  if (isServer) {
    return {
      foo: 'bar';
    };
  }
}

But this is verbose:

configureWebpack(isServer) {
  if (isServer) {
    return {
      foo: 'bar';
    };
  }
  return {};
}

It doesn't matter if you return {}, null, or undefined. As long as you explicitly return something, the syntax tax is the same. However, encouraging users to not return anything is encouraging bad coding practice that we don't want.

I think we could improve the error message, but nothing more. Returning {} is both semantically and practically good enough.

@slorber
Copy link
Collaborator

slorber commented Mar 2, 2022

I see

IMHO this is more config than real user code
I don't think the ESLint rules should apply in the same way for config so I'd still like to provide this shortcut to make user life easier. Users are responsible for their own codebase coding practices, we shouldn't annoy them to ask for an empty object where this could work without.

Not 100% the same but there are multiple places where we accept "partial" configs and try to infer a good general behavior

@yorkie
Copy link
Contributor Author

yorkie commented Mar 3, 2022

@yorkie I'm willing to merge this change but I'd like to have a test + a correct TS type
Let us know if you want help

I will add tests and fix typings later, thank you @slorber :)

@slorber slorber marked this pull request as draft March 3, 2022 08:55
@Josh-Cena
Copy link
Collaborator

Josh-Cena commented Mar 5, 2022

I still think that config is user code, but let's put stylistic preferences aside and talk about potential mistakes. What if the user made a mistake and forgot to write the return statement? These plugins are where the validation system can't cover. What about giving a nicer error message asking the user to explicitly return {}?

@slorber
Copy link
Collaborator

slorber commented Mar 9, 2022

What if the user made a mistake and forgot to write the return statement?

I don't know, this is something I would do myself on purpose.

If I am against the idea of using implicit return on purpose, I can bring my own eslint config or use TS to prevent it from happening.

We shouldn't force a user to absolutely have to return {} if they prefer using implicit undefined returns, like it's the case for 2/3 users of this PR :)

If things can work on the 1st try without asking users to read another error message and do additional tasks, that doesn't seem like a bad idea to me.

@Josh-Cena
Copy link
Collaborator

We shouldn't force a user to absolutely have to return {} if they prefer using implicit undefined returns, like it's the case for 2/3 users of this PR :)

Fair, I would be fine with Configuration | undefined then. Just totally unsure of the value🤷‍♂️ Null-safety is not something I like in general (I'd rather let it crash on undefined), unless a nullish value actually has semantic significance (as a "hole", for example).

@slorber
Copy link
Collaborator

slorber commented Mar 9, 2022

Slightly related choice: React allowing to render undefined: reactwg/react-18#75

@Josh-Cena Josh-Cena changed the title fix(core): allow configureWebpack to return undefined feat(core): allow configureWebpack to return undefined Mar 22, 2022
@Josh-Cena Josh-Cena marked this pull request as ready for review March 22, 2022 03:30
@Josh-Cena
Copy link
Collaborator

Josh-Cena commented Mar 22, 2022

After some pondering, I decided to not make typing changes. Otherwise, the return type would be Configuration | undefined | void which clearly stands out as an anti-pattern. We would warrant null-safety, but people who opt into stronger types should also write their code in a more sensible fashion.

@slorber If you read up that reactwg/react-18#75 thread, undefined is allowed for pragmatic reasons, because otherwise types are hard to write. That doesn't happen for us. "This should be the job of linters" doesn't warrant why React should allow undefined; it warrants why React can allow undefined, because it would be caught by other tools anyways. Implicitly returning undefined should still be frowned upon by all tooling, let it be TypeScript, ESLint, or React itself.

@Josh-Cena
Copy link
Collaborator

Merging this. I changed my mind because I realized we have null-safe lifecycles elsewhere, so at least we have precedents.

@Josh-Cena Josh-Cena merged commit 6b3d94a into facebook:main Mar 22, 2022
@yorkie yorkie deleted the patch-1 branch March 23, 2022 04:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CLA Signed Signed Facebook CLA pr: polish This PR adds a very minor behavior improvement that users will enjoy.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants