diff --git a/packages/fes-plugin-layout/src/index.js b/packages/fes-plugin-layout/src/index.js
index 8d4d47be..99325149 100644
--- a/packages/fes-plugin-layout/src/index.js
+++ b/packages/fes-plugin-layout/src/index.js
@@ -9,6 +9,8 @@ export default (api) => {
         utils: { Mustache }
     } = api;
 
+    const helper = require('./node/helper');
+
     api.describe({
         key: 'layout',
         config: {
@@ -25,7 +27,7 @@ export default (api) => {
 
     const absRuntimeFilePath = join(namespace, 'runtime.js');
 
-    api.onGenerateFiles(() => {
+    api.onGenerateFiles(async () => {
         const { name } = api.pkg;
 
         const HAS_LOCALE = api.hasPlugins(['@fesjs/plugin-locale']);
@@ -37,6 +39,25 @@ export default (api) => {
             ...(api.config.layout || {})
         };
 
+        // 路由信息
+        const routes = await api.getRoutes();
+        // 把路由的meta合并到menu配置中
+        userConfig.menus = helper.fillMenuByRoute(userConfig.menus, routes);
+
+        const icons = helper.getIconsFromMenu(userConfig.menus);
+
+        const iconsString = icons.map(
+            iconName => `import ${iconName} from '@ant-design/icons-vue/es/icons/${iconName}'`
+        );
+        api.writeTmpFile({
+            path: join(namespace, 'icons.js'),
+            content: `
+        ${iconsString.join(';\n')}
+        export default {
+            ${icons.join(',\n')}
+        }`
+        });
+
         api.writeTmpFile({
             path: absFilePath,
             content: Mustache.render(
diff --git a/packages/fes-plugin-layout/src/runtime/helpers/index.js b/packages/fes-plugin-layout/src/node/helper.js
similarity index 60%
rename from packages/fes-plugin-layout/src/runtime/helpers/index.js
rename to packages/fes-plugin-layout/src/node/helper.js
index a9795055..5b69e83b 100644
--- a/packages/fes-plugin-layout/src/runtime/helpers/index.js
+++ b/packages/fes-plugin-layout/src/node/helper.js
@@ -1,4 +1,4 @@
-export const noop = () => {};
+import * as allIcons from '@ant-design/icons-vue';
 
 const matchName = (config, name) => {
     let res = {};
@@ -21,7 +21,7 @@ const matchName = (config, name) => {
     return res;
 };
 
-export const fillMenuData = (menuConfig, routeConfig, dep = 0) => {
+export const fillMenuByRoute = (menuConfig, routeConfig, dep = 0) => {
     dep += 1;
     if (dep > 3) {
         throw new Error('[plugin-layout]: menu层级不能超出三层!');
@@ -39,11 +39,37 @@ export const fillMenuData = (menuConfig, routeConfig, dep = 0) => {
                     menu[prop] = pageConfig[prop];
                 }
             });
+            // 处理icon
+            if (menu.icon) {
+                const icon = menu.icon;
+                const iconName = `${icon.replace(icon[0], icon[0].toUpperCase())}Outlined`;
+                if (!allIcons[icon]) {
+                    menu.icon = iconName;
+                }
+            }
             if (menu.children && menu.children.length > 0) {
-                menu.children = fillMenuData(menu.children, routeConfig, dep);
+                menu.children = fillMenuByRoute(menu.children, routeConfig, dep);
             }
             arr.push(menu);
         });
     }
     return arr;
 };
+
+export function getIconsFromMenu(data) {
+    if (!Array.isArray(data)) {
+        return [];
+    }
+    let icons = [];
+    (data || []).forEach((item = { path: '/' }) => {
+        if (item.icon) {
+            const { icon } = item;
+            icons.push(icon);
+        }
+        if (item.children) {
+            icons = icons.concat(getIconsFromMenu(item.children));
+        }
+    });
+
+    return Array.from(new Set(icons));
+}
diff --git a/packages/fes-plugin-layout/src/runtime/index.tpl b/packages/fes-plugin-layout/src/runtime/index.tpl
index 55f2fd09..ce86b74a 100644
--- a/packages/fes-plugin-layout/src/runtime/index.tpl
+++ b/packages/fes-plugin-layout/src/runtime/index.tpl
@@ -1,7 +1,6 @@
 import { reactive, defineComponent } from "vue";
-import { getRoutes, plugin, ApplyPluginsType } from "@@/core/coreExports";
+import { plugin, ApplyPluginsType } from "@@/core/coreExports";
 import BaseLayout from "./views/BaseLayout.vue";
-import { fillMenuData } from "./helpers";
 
 const userConfig = reactive({{{REPLACE_USER_CONFIG}}});
 
@@ -14,8 +13,6 @@ const Layout = defineComponent({
             initialValue: {},
         });
         const localeShared = plugin.getShared("locale");
-        const routeConfig = getRoutes();
-        userConfig.menus = fillMenuData(userConfig.menus, routeConfig);
         return () => {
             const slots = {
                 customHeader: () => {
diff --git a/packages/fes-plugin-layout/src/runtime/views/Menu.vue b/packages/fes-plugin-layout/src/runtime/views/Menu.vue
index 05b4403f..264ae82a 100644
--- a/packages/fes-plugin-layout/src/runtime/views/Menu.vue
+++ b/packages/fes-plugin-layout/src/runtime/views/Menu.vue
@@ -50,7 +50,7 @@ import { toRefs, computed } from 'vue';
 import { useRoute, useRouter } from '@@/core/coreExports';
 import Menu from 'ant-design-vue/lib/menu';
 import 'ant-design-vue/lib/menu/style/css';
-import MenuIcon from './MenuIcon'
+import MenuIcon from './MenuIcon';
 import { addAccessTag } from '../helpers/pluginAccess';
 
 export default {
diff --git a/packages/fes-plugin-layout/src/runtime/views/MenuIcon.vue b/packages/fes-plugin-layout/src/runtime/views/MenuIcon.vue
index 1422f39d..d04c8f03 100644
--- a/packages/fes-plugin-layout/src/runtime/views/MenuIcon.vue
+++ b/packages/fes-plugin-layout/src/runtime/views/MenuIcon.vue
@@ -2,29 +2,21 @@
 // 使用 ant-design/icons-vue
 // 使用 本地 svg 图片
 // 使用 远程 svg 地址
-import { ref, onMounted } from 'vue';
+// eslint-disable-next-line import/extensions
+import Icons from '../icons';
 // import AntdIcon from '@ant-design/icons-vue/es/components/AntdIcon';
 export default {
     props: {
         icon: String
     },
     setup(props) {
-        const AIcon = ref(null);
-        onMounted(()=>{
-            const iconName = props.icon.slice(0, 1).toUpperCase() + props.icon.slice(1) + 'Outlined';
-            import(`@ant-design/icons-vue/es/icons/${iconName}`).then(res=>{
-                AIcon.value = res.default;
-            }).catch(e=>{
-                console.warn(`[fes-layout] icon ${props.icon} 不存在!`)
-            })
-        })
-        return ()=>{
-            if(AIcon.value){
-                return <AIcon.value />
+        const AIcon = Icons[props.icon];
+        return () => {
+            if (AIcon) {
+                return < AIcon />;
             }
-            return null
-        }
-
+            return null;
+        };
     }
-}
+};
 </script>