Problems encountered:
Recently, I encountered problems that everyone might encounter when writing a personal blog
Vue single page seems powerless when SEO, especially Baidu does not crawl dynamic scripts
Vue-Router and front-end separation cannot allow meta tags to be dynamically filled when spider crawling
Vue single page is the trend of the times, and it is more than just a pleasant one to write. Of course, you can also choose multiple pages
But even multiple pages cannot be used to generate Vue pages for each article when facing articles and documents
Of course SSR can solve this problem, but if you think about it carefully, isn't SSR the same as the previous .php page?
All data are pulled in advance and then filled and returned to the browser, which consumes more server resources and is cumbersome to configure.
Of course pre-rendering can't solve this problem either
So the question is, I just want Baidu to grab my dynamic article, but configuring a cumbersome SSR is not the best choice
My solution:
Since I just want Baidu to crawl my dynamic article, I actually want the spider to crawl my static page, the meta tag of the html has been filled
Then it's very simple. Wouldn't we just need to implement an extremely simple castrated version of SSR?
PS: I haven't found any related articles on Baidu for a long time. I don't know if my Baidu posture is wrong😅
Specific ideas:
Because my server backend language is php and service is nginx, all the backend code I show here is based on php. Of course, you can choose nodejs or other languages to implement it. Here is a simple idea
The above mentioned that we want to implement a castrated version of SSR. In fact, when the server requests it, it fills the data on the static html meta tag and returns it to the requesting end.
The implementations here are all based on the Vue single page that has been built, so please build a Vue single page first.
First, transform the built dist
Get the variable at the top, because the interfaces are ready-made, so just call the interface directly
<?php $valDescription = 'Front-end introduction, advanced summary records, personal log blogs, small nests for sharing web learning experience. '; $valKeywords = 'web nest, front-end, vue, js, blog, JavaScript, css, introduction, tutorial'; $valTitle = 'web nest'; /** * Method of sending HTTP request * @param string $url Request URL * @param array $params Request parameters * @param string $method request method GET/POST * @return array $data response data */ function http_Req($url, $params, $method = 'GET', $header = array("Content-type: text/html; charset=utf-8"), $multi = false){ if($method == 'POST'){ $header = ["Content-type: application/x-www-form-urlencoded"]; } $opts = array( CURLOPT_TIMEOUT => 30, CURLOPT_RETURNTRANSFER => 1, CURLOPT_SSL_VERIFYPEER => false, CURLOPT_SSL_VERIFYHOST => false, CURLOPT_HTTPHEADER => $header ); /* Set specific parameters according to request type */ switch(strtoupper($method)){ case 'GET': $opts[CURLOPT_URL] = $url . '?' . http_build_query($params); break; case 'POST': //Discern whether to transfer files $params = $multi ? $params : http_build_query($params); $opts[CURLOPT_URL] = $url; $opts[CURLOPT_POST] = 1; $opts[CURLOPT_POSTFIELDS] = $params; break; default: throw new Exception('Unsupported request method! '); } /* Initialize and execute curl request */ $ch = curl_init(); curl_setopt_array($ch, $opts); $data = curl_exec($ch); $error = curl_error($ch); curl_close($ch); if($error) throw new Exception('An error occurred in the request:' . $error); return $data; } //Splitting the path of the current request$urlExp = explode('/',$_SERVER['REQUEST_URI']); //If the current path is the content of the articleif(count($urlExp)>2 && $urlExp[1] == 'article'){ //Request the title and description of the current article $ret = json_decode(http_Req('http://127.0.0.1/api/Blog/getsinglelist',['tuid'=>$urlExp[2]],'POST'),true); $valKeywords = $ret['info'][0]['tt'].','.$valKeywords; $valDescription = $ret['info'][0]['txt'].' - '.$valTitle.','.$valDescription; $valTitle = $ret['info'][0]['tt'].' - '.$valTitle; } ?>
Output the obtained data to the meta tag
<meta name="description" content="<?php echo $valDescription; ?>"/> <meta name="keywords" content="<?php echo $valKeywords; ?>"/> <title><?php echo $valTitle; ?></title>
Then change the file name to
It's very rough, but there is only one function anyway, throw it here first
My service is nginx, Vue-Router is history mode, so when an html request comes over, I turn all the requests I originally turned to
This realizes a castrated version of SSR
The effect is like thisWeb nest
When each article is refreshed, the corresponding meta tag will be filled with data in advance.
Implement Vue-Router history mode with nginx
Of course, only history mode has the meaning of SEO
Just change the original place you turned in nginx configuration to, the same is true for Apache
location / { index ; alias /var/www/html/blog/; try_files $uri $uri/ /; }
Questions about backend interface requests
Because I have a server myself, the backend language is php
The framework used in php also requires pseudostatic
So my solution is to use nginx to configure the path accessed by the proxy based on the second-level domain name.
Similar to static resources, all the cdn secondary domain names are accessed, and the interface requests to access the API are accessed.
server { listen 80; listen 443 ssl; server_name ; root /var/blog; } server { listen 80; listen 443 ssl; server_name ; root /var/api; }
Of course you can simply configure it using the request path
server { listen 80; listen 443 ssl; server_name ; root /var; location ~ ^/api/ { alias /var/api; } location ~ ^/blog/ { alias /var/blog/; } }
This will separate the resource paths
Written at the end
I originally planned to implement it with nodejs, write an npm package, run a node process, and then nginx reversely proxy the request to the node port, which looks more elegant
But then I think my backend is php, and directly proxying to this php file can save time writing npm packages. The built html will have to be a little bit of trouble every time, and it is not elegant.
Here is more about providing an idea. If I have time later, maybe I will write an npm package to implement it elegantly
The above is all the content of this article. I hope it will be helpful to everyone's study and I hope everyone will support me more.