jaredpalmer / razzle

✨ Create server-rendered universal JavaScript applications with no configuration
https://razzlejs.org
MIT License
11.1k stars 866 forks source link

Add module federation example #1310

Closed ScriptedAlchemy closed 3 years ago

ScriptedAlchemy commented 4 years ago

🚀 Feature request

Current Behavior

Hey team, I spotted some movement on the WP5 branch and wanted to request that your config setup is compatible with ModuleFederationPlugin.

Desired Behavior

Pretty much, depending on how exposed you allow your config - to check that it works with ModuleFederationPlugin, I’ve had some challenges with Next.js and upgrading them to webpack then on top of that provisioning support for the new feature in v5 core.

Typically, for simplicity - id have some flag that ensures runtimeChunk is not set to single if the user decides to use MF

Suggested Solution

Install the plugin and make sure options can be passed to the end user. Your project is along a similar thread to next (I think) and is leveraged for micro-frontend type builds. Stitching layers have always been a tricky issue.

Routing between apps requires reloading pages and so on, duplicate vendor code, or externals have typically been depended on but have limits and inflexible restraints.

At webpack We have been working pretty hard to resolve this. Essentially allowing users to import() code from independent applications that are deployed separately and run standalone. It works with anything webpack can process today. Also working in the node runtime, enabling ssr to be stitched at runtime and software to be evergreen if users decide to use that capabilities.

Who does this impact? Who is this for?

It’s quite a big impact to users. Especially ones with challenges around scale and autonomy.

The feature is being shipped in angular around September. Being built into storybook, and Microsoft is moving as well.

The current code in the branch looks pretty new and I cannot foresee any potential issue supporting it or documenting how to enable it within your platform.

The implementation is very straightforward. Takes about 5 min to setup from scratch. And requires no syntactic or structural changes to user codebases. They simply use import and the parser will handle federated code accordingly by leveraging new module factories we designed in the core.

Describe alternatives you've considered

Honestly there’s not been an alternative to try. Which is why we made some major modifications to webpack core. I guess dll plugin is a rudimentary and context bound concept. But even so it’s at build time and quite static. Doesn’t really solve modern problems in distributed systems.

Additional context

I’m the creator of ModuleFederationPlugin, working very close with Tobias as we prepare beta.17 to enable more advanced implementations. If you’re considering using or supporting it - I should be able to answer any questions.

I’ve also got a decent number of resources, videos, articles and so on under the Federation organization https://github.com/module-federation/module-federation-examples

Let me know if I can provide any additional information!

maraisr commented 4 years ago

@jaredpalmer if you need any assistance in supporting this, I'd be keen to assist.

fivethreeo commented 4 years ago

Is there any tests we can look up to see how this works? 😃

fivethreeo commented 4 years ago

@maraisr any help on this and reviewing my pull requests will be appreciated also help with keeping the webpack5 pull in sync with next branch.

fivethreeo commented 4 years ago

@ScriptedAlchemy read a bit too fast, this should be doable. Could be a razzle plugin with config options.

StevenLangbroek commented 4 years ago

Hey folks! Not sure whether this was worth opening a bug report on, but I tried running razzle with webpack@5.0.0-beta.17, and I got this error as soon as I run yarn start:

ValidationError: Invalid options object. Watch Ignore Plugin has been initialized using an options object that does not match the API schema.
 - options[0] should be an object:
   object { paths }
 - options[1] should be an object:
   object { paths }
    at validate (/Users/stevenlangbroek/Code/poly-host/node_modules/schema-utils/dist/validate.js:96:11)
    at new WatchIgnorePlugin (/Users/stevenlangbroek/Code/poly-host/node_modules/webpack/lib/WatchIgnorePlugin.js:88:3)
    at module.exports (/Users/stevenlangbroek/Code/poly-host/node_modules/razzle/config/createConfig.js:304:9)
    at main (/Users/stevenlangbroek/Code/poly-host/node_modules/razzle/scripts/start.js:76:20)
    at processTicksAndRejections (internal/process/task_queues.js:97:5) {
  errors: [
    {
      keyword: 'type',
      dataPath: '[0]',
      schemaPath: '#/type',
      params: [Object],
      message: 'should be object',
      schema: 'object',
      parentSchema: [Object],
      data: '/Users/stevenlangbroek/Code/poly-host/build/assets.json'
    },
    {
      keyword: 'type',
      dataPath: '[1]',
      schemaPath: '#/type',
      params: [Object],
      message: 'should be object',
      schema: 'object',
      parentSchema: [Object],
      data: '/Users/stevenlangbroek/Code/poly-host/build/chunks.json'
    }
  ],
  schema: {
    title: 'WatchIgnorePluginOptions',
    type: 'object',
    additionalProperties: false,
    properties: { paths: [Object] },
    required: [ 'paths' ]
  },
  headerName: 'Watch Ignore Plugin',
  baseDataPath: 'options',
  postFormatter: null
}

This is before even modifying webpack config.

Steps:

$ yarn create razzle-app my-app
$ cd my-app
$ yarn add webpack@beta
# select beta 16 or 17
# add to package.json resolutions
$ yarn
$ yarn start
fivethreeo commented 4 years ago

We are working on webpack5 support. I have a webpack5 branch in my razzle GitHub repo. I need to rebase it on the next branch in this repo. So currently there is no webpack5 support in razzle .

StevenLangbroek commented 4 years ago

I understand, just thought it was worth bringing up in the context of ongoing work.

fivethreeo commented 4 years ago

https://github.com/jaredpalmer/razzle/tree/webpack5 - for those that want to try their luck :)

ScriptedAlchemy commented 4 years ago

If you get stuck, Ive got an enormus amount of context into webpack beta.17

StevenLangbroek commented 4 years ago

@fivethreeo ran into 2 bugs on the webpack5 branch (1 with beta16 and 1 with beta17). Do you want me to report them or is this still in progress to such an extent that bug reports aren't super helpful?

StevenLangbroek commented 4 years ago

Ok it's just 1 thing, I'd made a mistake when linking. Basically chalk is being included in the client-side bundle for some reason... Any idea why that would happen?

image

fivethreeo commented 4 years ago

@StevenLangbroek hm, strange, what is the os and node version?

StevenLangbroek commented 4 years ago

@fivethreeo it's OSX 10.15.3 and Node 12 and 14 (tried with both). I've resolved it for now by removing webpackHotDevClient.js from entry.

fivethreeo commented 4 years ago

@StevenLangbroek how did you install the packages?

StevenLangbroek commented 4 years ago

@fivethreeo I added webpack@5.0.0-beta.17 to resolutions in my package.json, cloned razzle, checked out the webpack5 branch, ran lerna bootstrap, and then yarn linkeded razzle from packages/razzle.

fivethreeo commented 4 years ago

@StevenLangbroek can you try using

yarn install --frozen-lockfile --ignore-engines --network-timeout 30000

In razzle webpack5 checkout

Then run

yarn test

Then yarn link razzle-dev-utils and razzle to your project without adding webpack5 to your projects package.json

StevenLangbroek commented 4 years ago

@fivethreeo that leads to this error (which I guess is because it's running webpack 4 instead of 5 if i don't add it to resolutions):

Error: Cannot find module 'webpack/lib/container/ModuleFederationPlugin'
Require stack:
- /Users/stevenlangbroek/Code/poly-host/razzle.config.js
- /Users/stevenlangbroek/Code/razzle/packages/razzle/config/loadRazzleConfig.js
- /Users/stevenlangbroek/Code/razzle/packages/razzle/scripts/start.js
StevenLangbroek commented 4 years ago

Test output when running yarn test in razzle/webpack5:

image

fivethreeo commented 4 years ago

Ok, getting closer, to the test problem atleast, might be just a scss problem :)

node -e 'require("./test/fixtures/util").setupStageWithExample("example", "with-scss-options", symlink=false, yarnlink=true, install=true, test=false);'  

cd example
yarn build
StevenLangbroek commented 4 years ago

image

fivethreeo commented 4 years ago

Ok, so a unrelated fail in tests. Might be yarn link related somehow.

StevenLangbroek commented 4 years ago

If all of this is distracting from what I imagine is a lot of work, I hope you'll let me know. If there's anything else I can do to contribute I can make some time for it.

fivethreeo commented 4 years ago

No problem, it is just that we have so nice weather here right now, so basking in the sun instead of sitting at the computer all day 😃

Also I don’t have OS X. So hard to debug this.

The scss error is on node 13/14?

fivethreeo commented 4 years ago

Can you post your package json?

ScriptedAlchemy commented 4 years ago

I’ll pull down this branch next week and take a look as well :)

StevenLangbroek commented 4 years ago

@fivethreeo here you go:

{
  "name": "my-razzle-app",
  "version": "0.1.0",
  "license": "MIT",
  "scripts": {
    "start": "razzle start",
    "build": "razzle build",
    "test": "razzle test --env=jsdom",
    "start:prod": "NODE_ENV=production node build/server.js"
  },
  "resolutions": {
    "webpack": "5.0.0-beta.17"
  },
  "dependencies": {
    "antd": "^4.3.3",
    "express": "^4.17.1",
    "razzle": "^3.1.3",
    "react": "16",
    "react-dom": "16",
    "react-router-dom": "^5.2.0"
  }
}
fivethreeo commented 4 years ago

try without antd to keep it basic and make sure only one webpack version is installed, just a idea on trying to figure out why it does not work so we can try fixing it properly :)

StevenLangbroek commented 4 years ago

@fivethreeo I did (added it later to try something out)

fivethreeo commented 4 years ago

Maybe yarn link and yarn install combined with resolveLoaders somehow gets the wrong webpack.

Does this work?

node -e 'require("./test/fixtures/util").setupStageWithExample("example", "basic", symlink=false, yarnlink=true, install=true, test=false);'  

cd example
yarn build
fivethreeo commented 4 years ago

Added 2 fixes to webpack5 branch now, I saw your test run had more test failures too. Can you retry now?

fivethreeo commented 4 years ago

@StevenLangbroek maybe this is the issue https://github.com/facebook/create-react-app/issues/8583 , maybe two react-dev-utils versions somehow?

fivethreeo commented 4 years ago

@StevenLangbroek updated sass dependencies in the branch now, may fix your sass issue :)

fivethreeo commented 4 years ago

You can try doing yarn why on razzle and razzle-plugin-scss dependencies to see if you have conflicting packages and add razzle's version of the dependency to resolutions in your package.json if you find any conflicts.

fivethreeo commented 4 years ago

Should be possible to try webpack5 in razzle now.

To try it now:

npx create-razzle-app@canary testing --ignore-existing
cd testing
yarn add webpack@5.0.0-rc.3 --dev
yarn start
yarn build
yarn start:prod
yarn test

See the docs

ScriptedAlchemy commented 4 years ago

We released webpack 5 stable this morning. It's now released on npm.

I've forgotten about this issue - but if there is active work ongoing to integrate MF, give me a quick update and I'll jump in (thread is long)

I've just started working to bring Nuxt to MF capabilities and next.js is already under way.

Is there a branch?

fivethreeo commented 4 years ago

There is the canary branch, it has webpack5 support. I think this is mostly about making a example project.

ScriptedAlchemy commented 4 years ago

Yeah pretty much. And ensuring that you have async imports on place at the entrypoint so vendor code can be shared. Check my module federation examples to get a feel for what I add to repos. The entrypoint always has an async import to the actual entrypoint code. This lets us share static imports like react without the app crashing. We have issues with next because it uses multiple entry points for pages and everything is sync

fivethreeo commented 3 years ago

It works, example added https://github.com/jaredpalmer/razzle/tree/canary/examples/with-module-federation

npx create-razzle-app@canary basic --example with-module-federation --no-install cd basic yarn install yarn start

http://localhost:3000/ http://localhost:3001/