Upgrade to Pro — share decks privately, control downloads, hide ads and more …

202110-federation

milkmidi
September 24, 2021

 202110-federation

milkmidi

September 24, 2021
Tweet

More Decks by milkmidi

Other Decks in Programming

Transcript

  1. 今天的主角 webpack5 Federation Plugin https://webpack.js.org/concepts/module-federation/ Module Federation 是什麼 ? 一種

    JavaScript 的微前端架構 可以讓一個 JS 動態載入另一個專案的元件 聽起來是不是超爽的
  2. 來人呀,上 Code A 站,暫稱 Provider // webpack.config.js output: { publicPath:

    ‘http://localhost:9527/’, 這裡一定要是絕對路徑 }, new ModuleFederationPlugin({ name: ‘milkmidiLibrary’, // Module 名稱(會變成 window 變數) filename: ‘remoteEntry.js’, // 打包後的檔名 exposes: { // 想要共用的元件 './MyButton': './src/components/MyButton.vue', './MyModel': './src/libs/MyModel', './useDataWithLodash': './src/hooks/useDataWithLodash', }, })
  3. MyModel.ts 沒載入任何第三方 package export const add = (a:number, b:number):number =>

    a + b; const config = { name: 'milkmidi-MyModel', value: '發大財', }; export default config;
  4. useDataWithLodash.ts import { reactive, onMounted } from 'vue'; import _

    from 'lodash'; export type UseFetchDataType = { isLoading : boolean; data?: string; } const useFetchData = ():UseFetchDataType => { const state:UseFetchDataType = reactive({ data: undefined, isLoading: false, }); onMounted(async () => { state.isLoading = true; state.data = _.get({ name: 'milkmidi' }, 'name'); state.isLoading = false; }); return state; }; export default useFetchData;
  5. Shared // webpack.config.js const deps = require('./package.json').dependencies; new ModuleFederationPlugin({ 略

    shared: { ...deps, vue: { // 這個參數是重點。ture 的話,會先把有用到的 node_modules 都先包裡來 // eager: true, // 奶綠覺得不要打開 // only a single version of the shared module is allowed singleton: true, // strictVersion: true, // 開了 host 和 remote 就會需要一樣的版本 requiredVersion: deps.vue, }, } })
  6. bootstrap.js (不是那個 bootstrap css) // bootstrap.js import { createApp }

    from 'vue'; import App from './App.vue'; createApp(App) .mount('#root'); // index.js import { createApp } from 'vue'; import App from './App.vue'; createApp(App) .mount('#root’); import('./bootstrap');
  7. 來人呀,上 Code B 站,暫稱 host (B 站沒安裝 lodash) // webpack.config.js

    new ModuleFederationPlugin({ remotes: { milkmidiLibrary: 'milkmidiLibrary@http://localhost:9527/remoteEntry.js', }, shared: { ...deps, vue: { 略 }, }, }),
  8. B 站 一樣要有 bootstrap.js // 就像一般的寫法,直接當 module import, 超爽 import

    MyModel, { add } from 'milkmidiLibrary/MyModel'; import MyButton from 'milkmidiLibrary/MyButton'; import useDataWithLodash from 'milkmidiLibrary/useDataWithLodash’; export default { setup() { const state = useDataWithLodash(); return { state, }; }, mounted() { console.log(MyModel); console.log('MyModel.add(1,1) = ', add(1, 1)); }, }; </script> <template> <div id="app"> <h1>Host</h1> <MyButton /> <MyButton :default-value="10" /> /div> </template>
  9. 來人呀,上 Code C 站 , 不要用 bootstrap + 使用 script

    載入 // webpack.config.js new ModuleFederationPlugin({ remoteType: 'var', remotes: { milkmidiLibrary: 'milkmidiLibrary', }, shared: { vue: { // 如果沒有 bootstrap, 所有用到的 shared 都需要打開 eager eager: true, 略 }, }, }), // index.html <script src="http://localhost:9527/remoteEntry.js" defer></script>
  10. import('milkmidiLibrary/MyModel').then((myModel) => {}); const MyButton = defineAsyncComponent(() => import('milkmidiLibrary/MyButton’)); export

    default { setup() { const state = reactive({ data: undefined, isLoading: false, }); // 在這樣的情況下,就會無解,因為 hooks 不能是非同步載入 // 還是其實可以? (我要 tag kuro 大大), 至少我確定 react 不行 import('milkmidiLibrary/useDataWithLodash').then((module) => { const result = module.default(); console.log(result); state.isLoading = result.isLoading; state.data = result.data; // not work. OOP }); return { state, }; }, }; </script>