基于SPA的项目,打包出来的文件中只有一个index.html做为入口,再根据页面的路由加载对应页面的js。html
当项目须要支持SEO时,在条件容许的状况下能够选择node做为同构方案,根据url匹配routes中的components,再经过rendersToString方法打印出内容,放到html模板中。此方案的优势是能够支持动态路由、后端获取数据。缺点是每次访问都要生成一次、引进了node服务。node
若是在网站被访问以前就把html预编译好,多个路由对应多个html。后端
在umi项目中配置预编译很是简单
umirc.js浏览器
plugins: [['@umijs/plugin-prerender']], ssr: true,
把umirc.js中ssr设置成true后,dist文件夹下就多生成了一个umi.server.js文件,它是以/src/pages/.umi文件为入口、囊括了其余全部dist/*.js生成的大文件,而且通过了一些环境上的处理。网站
/src/pages/.umi是每次打包后都会生成的中间结果,查看代码会发现它是以__IS_BROWSER变量区分浏览器、node环境,而umi.server.js则是把__IS_BROWSER变量替换成boolean的结果,所以在业务代码中,能够直接使用__IS_BROWSER这一变量区分你的逻辑。例如,页面中一开始有loading等待缓冲的效果,可使用__IS_BROWSER将loading取消,避免编译出来的内容无效。url
在预编译以前,想要给html中放入一些内容,但这些内容又不须要在实际业务中展现。这时能够选择给routes下定义的component添加getInitialProps方法插件
function Index(props){ return props.nodeContent || 'hello world' } Index.getInitialProps = ()=>({ nodeContent: '个人seo内容' }) export defalut Index
将不常常更新的内容放到getInitialProps中写死,生成的内容供seo抓取,不过在js执行后会将其刷新掉。ssr
umi-server在调用umi.server.js时会给global变量附加mock过的window对象,例如,在业务代码中访问window.location.url时,获取到的是浏览器环境同样的结果。code
pre-render插件在umi打包结束后,按照routes里的url一个个访问ssr,相似于构造虚拟访问来生成html。component
routes除非指定了黑白名单,不然将生成全部html
umirc.js
[ '@umijs/plugin-prerender', { include: ['/'], exclude: ['/help'] }, ]
umi默认给图片加了阈值,当小于这个值时生成的图片使用base64。但在预编译时生成的html中会产生大量的base64字符,使得html变大。
这里能够设置图片的阈值,减少html的包袱
umirc.js
chainWebpack(config) { config.module .rule('exclude') .use('url-loader') .tap((options) => { return { ...options, limit: 1, }; }); }
最新的umi版本已经解决了动态路由的问题,例如/:id的路由会生成[id].html。若是项目中的动态路由可枚举,将动态路由改形成一个个写死的路由,这样再生成多个html。这样作的目的是生成更多的html让seo引擎抓取。若是项目中的动态路由没法枚举,或访问方式有太多种,则须要借助后端动态实时生成。