vite-plugin-seo-prerender
Version:
`vite-plugin-seo-prerender` 插件是一个用于 `Vite` 构建工具的预渲染插件,它可以将你的单页面应用 (SPA) 在构建时静态预渲染为 HTML 文件,以提高首次加载速度和SEO友好性。适用于对站点少量页面生成静态HTML。支持 `Vue、React`等所有框架
10 lines (9 loc) • 6.37 kB
JavaScript
/**
* name: vite-plugin-seo-prerender
* version: 1.1.1
*/
;var z=Object.create;var w=Object.defineProperty;var G=Object.getOwnPropertyDescriptor;var N=Object.getOwnPropertyNames;var V=Object.getPrototypeOf,J=Object.prototype.hasOwnProperty;var K=(t,e)=>{for(var s in e)w(t,s,{get:e[s],enumerable:!0})},C=(t,e,s,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of N(e))!J.call(t,n)&&n!==s&&w(t,n,{get:()=>e[n],enumerable:!(r=G(e,n))||r.enumerable});return t};var p=(t,e,s)=>(s=t!=null?z(V(t)):{},C(e||!t||!t.__esModule?w(s,"default",{value:t,enumerable:!0}):s,t)),Q=t=>C(w({},"__esModule",{value:!0}),t);var rt={};K(rt,{default:()=>et});module.exports=Q(rt);var I=p(require("child_process"),1),h=p(require("path"),1),O=p(require("fs"),1),B=p(require("sass"),1);var T=p(require("puppeteer"),1),E=p(require("fs"),1),k=p(require("path"),1);var x=p(require("fs"),1),F=p(require("path"),1),y=t=>t&&t.replace(/\\/g,"/"),b=t=>{let e=F.default.dirname(t);x.default.existsSync(e)||b(e),x.default.existsSync(t)||x.default.mkdirSync(t)};function U(t,e=5){let s=t.length,r=0,n=[],i=(l,a,f)=>(n.push({index:l,result:a,error:f}),o()),o=()=>{if(r>=s)return Promise.resolve();let l=r++;return t[l]().then(a=>i(l,a)).catch(a=>i(l,null,a))},c=Math.max(1,Math.min(e,s)),u=[];for(let l=0;l<c;l++)u.push(o());return Promise.allSettled(u).then(()=>n.sort((l,a)=>l.index-a.index))}var M=require("url");function X(t){return new Promise(e=>setTimeout(e,t))}var Y=async t=>{let e=await T.default.launch(Object.assign({headless:"new"},t.puppeteer||{})),s="[vite-plugin-seo-prerender:routes]",r={};t.network&&(r={waitUntil:"networkidle0"});let n=new M.URL(t.base,t.local).toString().slice(0,-1),i=t.routes.length,o=0,c=async a=>{let f=await e.newPage();try{let S=n+a;t.hashHistory&&(S=`${n}/#${a}`),await f.goto(S,r),await f.setViewport({width:1024,height:768}),await f.waitForSelector("body"),t.delay&&await X(t.delay);let g=await f.content();t.removeStyle!==!1&&(g=g.replace(/<style\b[^<]*(?:(?!<\/style>)<[^<]*)*<\/style>/gi,""));let q=new RegExp(t.local,"g");if(g=g.replace(q,""),t.callback&&(g=t.callback(g,a)||g),a.indexOf("?")!==-1)console.log(`${s} ${a} is error,unexpected?`);else{let D=k.default.join(t.outDir,a);b(D);let $=k.default.join(D,"index.html");E.default.writeFileSync($,g),console.log(`[${o++}/${i}]${s} ${S.replace(t.local,"")} => ${$.replace(/\\/g,"/")} is success!`)}}finally{await f.close()}},u=t.routes.map(a=>()=>c(a)),l=Math.min(Math.max(1,Number(t.concurrency||1)),i);console.log(`${s} \u5F00\u59CB\u9884\u6E32\u67D3\uFF0C\u5E76\u53D1\u6570: ${l}`),await U(u,l),await e.close(),console.log(`${s} is complete`)},H=Y;var m=p(require("fs"),1),d=p(require("path"),1);var P="",Z=(t,e,s)=>{let r=m.default.readFileSync(d.default.join(t,"index.html"),"utf-8");if(e==="server"){let n=/<script[^>]*?\b\/main\b[^>]*?>.*?<\/script>/gi;return(r.match(n)||[]).join(`
`)}else{let n=/<link[^>]*?rel=['|"]stylesheet['|"][^>]*?\.css[^>]*?>/gi,i=r.match(n),c=m.default.readFileSync(d.default.join(t,s||"","index.html"),"utf-8").match(n)||[],u=c;return i&&(u=c.filter(l=>!i.includes(l))),u.join(`
`).replace('"./','"/')}},L=(t,e)=>t.replace(/<!--link\shref="(.*)"-->/gi,function(s,r){let n=d.default.join(e,r);return m.default.existsSync(n)?m.default.readFileSync(n,{encoding:"utf8"}):s}),R=(t,e,s)=>{let n=m.default.readFileSync(e,"utf-8").replace("</head>",`${P}
</head>`);n=L(n,t),typeof s=="function"&&(n=s(n,e)||n),m.default.writeFileSync(e,n),console.log("[vite-plugin-seo-prerender:publicHtml] "+y(d.default.relative(t,e)))},A=(t,e,s,r)=>{if(!m.default.existsSync(t)){console.log(`${t}\u8DEF\u5F84\u4E0D\u5B58\u5728`);return}m.default.readdirSync(t).forEach(i=>{let o=d.default.join(t,i);m.default.statSync(o).isFile()&&d.default.extname(o)===".html"&&!y(o).endsWith(e)&&R(s,o,r),m.default.statSync(o).isDirectory()&&A(o,e,s,r)})},_=async t=>{let{mode:e,root:s,filePath:r,outDir:n=""}=t;if(P||(P=Z(s,e,n)),e==="server"){let i=d.default.join(s,"public",r),o=m.default.readFileSync(i,"utf-8");return o=o.replace("</body>",`${P}
</body>`),o=L(o,s),typeof t.callback=="function"&&(o=t.callback(o,r)||o),o}else if(typeof r=="boolean"){let i=d.default.join(s,n),o=y(d.default.join(n,"index.html"));A(i,o,s,t.callback)}else for(let i in r){let o=d.default.join(s,n,r[i]);R(s,o,t.callback)}},v=_;var j=t=>{let e=[];return typeof t=="object"&&(e=t||[]),{allUrl:e,isAllUrl:typeof t=="boolean"&&t}},W=(t,e)=>{let s=h.default.join(t,e.entry),r=B.compile(s),n=h.default.join(t,e.outDir);b(h.default.dirname(n)),O.default.writeFileSync(n,r.css),console.log(`transform scss: ${e.entry} => ${e.outDir}`)},tt=t=>{let e={outDir:"",mode:"",root:"",local:"",base:"",isProduction:!1,command:""},s=t.publicHtml||!1;return{name:"vitePluginSeoPrerender",enforce:"post",configResolved(r){e.outDir=r.build.outDir,e.mode=r.mode,e.root=r.root,e.base=r.base,e.isProduction=r.isProduction,e.command=r.command},buildStart(){var r;(r=t==null?void 0:t.scss)!=null&&r.length&&t.scss.forEach(n=>{W(e.root,n)})},configureServer(r){let{allUrl:n,isAllUrl:i}=j(s);(n.length||i)&&r.middlewares.use(async(o,c,u)=>{let l=decodeURIComponent(o.url.replace(e.base,"/"));if(i&&l.endsWith(".html")||n.includes(l)){let a=await v({root:e.root,filePath:l,mode:"server",callback:t.callback});if(a){c.setHeader("Content-Type","text/html"),c.end(a);return}}u()})},handleHotUpdate({file:r,server:n}){var i;if(r.endsWith(".html")){let{allUrl:o,isAllUrl:c}=j(s);if(c||o.length){let u=h.default.join(e.root,"public"),l=h.default.relative(u,r);n.ws.send({type:"full-reload",path:"/"+y(l)})}}if((i=t==null?void 0:t.scss)!=null&&i.length&&r.endsWith(".scss")){let o=y(r);t.scss.forEach(c=>{o.includes(c.entry)&&W(e.root,c)})}},async closeBundle(){var c;if(!e.isProduction)return;let{allUrl:r,isAllUrl:n}=j(s);if((n||r.length)&&await v({root:e.root,filePath:n||r,mode:"build",outDir:e.outDir,callback:t.callback}),!((c=t==null?void 0:t.routes)!=null&&c.length))return;console.log("[vite-plugin-seo-prerender:routes] is start..");let i=I.default.exec("vite preview",u=>{if(u){console.error("\u6267\u884C\u547D\u4EE4\u65F6\u53D1\u751F\u9519\u8BEF\uFF1A",u);return}}),o="";i.stdout.on("data",async u=>{let l=u.match(/http:\/\/(.*?)\//g);l&&l.length&&!o&&(o=l[0].replace(/\x1B\[\d+m/g,"").slice(0,-1),console.log("Local: "+o),e.local=o,await H(Object.assign(e,t)),i.kill("SIGTERM"),process.exit(),o="")})}}},et=tt;