Coder Social home page Coder Social logo

ptzagk / vite-plugin-federation Goto Github PK

View Code? Open in Web Editor NEW

This project forked from originjs/vite-plugin-federation

0.0 0.0 0.0 1.21 MB

Module Federation for vite & rollup

License: Other

JavaScript 23.33% TypeScript 51.53% HTML 3.24% Vue 21.64% CSS 0.13% EJS 0.09% Shell 0.04%

vite-plugin-federation's Introduction

English | 简体中文

vite-plugin-federation

Build Status Version Node Compatibility License

A Vite plugin which support Module Federation. Inspired by Webpack [Module Federation](https://webpack.js.org/concepts/module-federation/) feature.

Application and practice

image-20211210105354887

Install

Using npm:

npm install @originjs/vite-plugin-federation --save-dev

Usage

The main steps in using federation are:

Step 1: change the configuration

  • for a Vite project, in vite.config.js:
import { defineConfig } from 'vite'
import federation from "@originjs/vite-plugin-federation";

export default defineConfig({
  plugins: [
    federation({
      name: 'module-name',
      filename: 'remoteEntry.js',
      exposes: {
        './Button': './src/Button.vue',
      },
      remotes:{
          foo: 'remote_foo'
      },
      shared: ['vue']
    })
  ],
})
  • for a Rollup project, in rollup.config.js:
import federation from '@originjs/vite-plugin-federation'


export default {
  input: 'src/index.js',
  output: {
    format: 'esm',
    dir: 'dist'
  },
  plugins: [
    federation({
      filename: 'remoteEntry.js',
      exposes: {
        './Button': './src/button'
      },
      shared: ['react']
    })
  ]
}

Step 2: asynchronous references

Vue2, for example

<script>
export default {
  name: 'App',
  components: {
    RemoteButtonScoped: () => import('remote-simple/remote-simple-button-scoped'),
  }
}
</script>

Step 3: Use Remote module components

Vue2, for example

<template>
  <div>
  		<RemoteButtonScoped />
  </div>
</template>

Configuration description

exposes

name: string


Required as the module name of the remote module.


filename:string


As the entry file of the remote module, not required, default is remoteEntry.js

As the remote module, the list of components exposed to the public, required for the remote module.

exposes: {
// 'externally exposed component name': 'externally exposed component address'
    '. /remote-simple-button': '. /src/components/Button.vue',
        '. /remote-simple-section': '. /src/components/Section.vue'
},

remotes

The remote module entry file referenced as a local module

configuration information

external:string|Promise<string>


remote module address, e.g. https://localhost:5011/remoteEntry.js You can simply configure it as follows

remotes: {
  // 'remote module name': 'remote module entry file address'
  'remote-simple': 'http://localhost:5011/remoteEntry.js',
}

Or do a slightly more complex configuration, if you need to use other fields

remotes: {
    remote-simple: {
        external: 'http://localhost:5011/remoteEntry.js',
        format: 'var',
    }
}

enternalType: 'url'|'promise'

default: 'url'


set the type of external

If you want to use a dynamic url address, you can set the external as promise, but please note that you need to set the externalType as 'promise' at the same time, and please ensure that the code of the promise part is correct, otherwise the package may fail,here is a simple example.

remotes: {
      home: {
          external: `Promise.resolve('your url')`,
          externalType: 'promise'
      },
},
    
// or from networke
remotes: {
    remote-simple: {
        external: `fetch('your url').then(response=>response.json()).then(data=>data.url)`,
        externalType: 'promise'
    }
}

format:'esm'|'systemjs'|'var'

default:'esm'
Specify the format of the remote component, this is more effective when the host and the remote use different packaging formats, for example the host uses vite + esm and the remote uses webpack + var, in which case you need to specify type : 'var'


from : 'vite'|'webpack'

default : 'vite'

Specify the source of the remote component, from vite-plugin-federation select vite, from webpack select webpack

shared

Dependencies shared by local and remote modules. Local modules need to configure the dependencies of all used remote modules; remote modules need to configure the dependencies of externally provided components.

configuration information

import: boolean

default: true


The default is true, whether to add shared to the module, only for the remote side, remote will reduce some of the packaging time when this configuration is turned on, because there is no need to package some of the shared, but once there is no shared module available on the host side, it will report an error directly, because there is no fallback module available


shareScope: string

default: 'default'


Default is defualt, the shared domain name, just keep the remote and host sides the same


version: string


Only works on host side, the version of the shared module provided is version of the package.json file in the shared package by default, you need to configure it manually only if you can't get version by this method


requiredVersion: string


Only for the remote side, it specifies the required version of the host shared used, when the version of the host side does not meet the requiredVersion requirement, it will use its own shared module, provided that it is not configured with import=false, which is not enabled by default

Examples

Construct

vite-plugin-federation dependencies are required during the development and build process, and global installation is recommended.

  • rollup
  • vite

Part of example requires dependencies, recommended for global installation.

  • lerna
  • rimraf

Github CI build, not engineering required:

  • playwright-chromium

Development mode

Since Vite is esbuild-based in development mode, we provide separate support for the development mode to leverage Vite’s high-performance development capabilities in the case of remote module deployment. And note that only Host supports the dev mode and Remote supports only build mode

Integration with webpack

⚠️: Please don't use heterogeneous components in React projects (e.g. vite using webpack components or vice versa), because there is no guarantee that vite/rollup and webpack will convert export consistent chunk when packaging the commonjs framework, which is a prerequisite for using shared is a prerequisite for using

Now you can use federation without the restrictions of vite and webpack, that is, you can choose to use the vit-plugin-federation component in webpack or the webpack-module- federation in vite, but you need to pay attention to the configuration in remotes, for different frameworks you need to specify remotes.from and remotes.format to make them work better, the currently supported format pairings are as follows.

host remote demo
rollup/vite+esm rollup/vite+esm simple-react-esm
rollup/vite+systemjs rollup/vite+systemjs vue3-demo-esm
rollup/vite+systemjs webpack+systemjs vue3-demo-systemjs
rollup/vite+esm webpack+var vue3-demo-webpack-esm-var
rollup/vite+esm webpack+esm vue3-demo-webpack-esm-esm

⚠️: vite is relatively easy to use with webpack components, but vite-plugin-federation components are better in esm format when webpack uses vite components, because other formats temporarily lack test cases to complete the test

Static Import

Static import is supported at this stage. The following shows the difference between the two methods. You can see examples of dynamic import and static import in each project in examples, and here is a simple example.

  • Vue
// dynamic import
const myButton = defineAsyncComponent(() => import('remote/myButton));
app.component('my-button' , myButton);
// or
export default {
  name: 'App',
  components: {
    myButton: () => import('remote/myButton'),
  }
}


// static import
import myButton from 'remote/myButton';
app.component('my-button' , myButton);
// or
export default {
  name: 'App',
  components: {
    myButton: myButton
  }
  • React
// dynamic import
const myButton = React.lazy(() => import('remote/myButton'))

// static import
import myButton from 'remote/myButton'

FAQ

The component of the remote module can not be displayed properly. The console displays“[Vue warn]: Invalid VNode type: Symbol() (symbol)”

The loading of the respective Vueby local and remote modules causes the problem of referencing multiple Vue.

Solutions:

Keep the local module relatively consistent with the dependent version shared in the remote module.

remote module's vite.config.ts

federation({
  name: 'common-lib',
  filename: 'remoteEntry.js',
  exposes: {
	'./CommonCounter': './src/components/CommonCounter.vue',
	'./CommonHeader': './src/components/CommonHeader.vue'
  },
  shared: {
	vue: {
	  requiredVersion:'^2.0.0' // If you force the version to be too low, delete or modify it to ^ 3.0.0
	}
  }
})

The remote module failed to load the share of the local module, for examplelocalhost/:1 Uncaught (in promise) TypeError: Failed to fetch dynamically imported module: http://localhost:8080/node_modules/.cacheDir/vue.js?v=4cd35ed0

Reason: Vite has auto fetch logic for IP and Port when starting the service, no full fetch logic has been found in the Plugin, and in some cases a fetch failure may occur.

Solutions:

Explicitly declaring IP, Port, cacheDir in the local module ensures that our Plugin can correctly fetch and pass the dependent addresses.

Local module's vite.config.ts

export default defineConfig({
  server:{
    https: "http",
    host: "192.168.56.1",
    port: 5100,
  },
  cacheDir: "node_modules/.cacheDir",
}

Wiki

Design framework

vite-plugin-federation's People

Contributors

adolph-wsy avatar chelestewang avatar danielkov avatar flyfishzy avatar genffy avatar lfbergee avatar ruleeeer avatar timehello avatar wangsongc avatar ygj6 avatar zgid123 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.