方案来源:https://github.com/tuoxiaozhong/vue-seo-phantomjs
1.安装 PhantomJS
-
下载 PhantomJS
-
从官网http://phantomjs.org/download.html下载linux64位的安装包即 phantomjs-2.1.1-linux-x86_64.tar.bz2
-
-
解压 phantomjs-2.1.1-linux-x86_64.tar.bz2
-
把安装包 放到 /usr/local
-
解压安装包
tar xjf phantomjs-2.1.1-linux-x86_64.tar.bz2
-
重命名
mv phantomjs-2.1.1-linux-x86_64 ./phantomjs
-
-
安装依赖软件
yum -y install fontconfig
-
建立软链接
ln -s /usr/local/phantomjs/bin/phantomjs /usr/bin/
-
验证是否安装成功(输出版本号则成功)
phantomjs -v
2.创建 spider.js
/*global phantom*/
"use strict";
// 单个资源等待时间,避免资源加载后还需要加载其他资源
var resourceWait = 500;
var resourceWaitTimer;
// 最大等待时间
var maxWait = 1000;
var maxWaitTimer;
// 资源计数
var resourceCount = 0;
// PhantomJS WebPage模块
var page = require('webpage').create();
// NodeJS 系统模块
var system = require('system');
// 从CLI中获取第二个参数为目标URL
var url = system.args[1];
// 设置PhantomJS视窗大小
page.viewportSize = {
width: 1280,
height: 1014
};
// 获取镜像
var capture = function(errCode){
// 外部通过stdout获取页面内容
console.log(page.content);
// 清除计时器
clearTimeout(maxWaitTimer);
// 任务完成,正常退出
phantom.exit(errCode);
};
// 资源请求并计数
page.onResourceRequested = function(req){
resourceCount++;
clearTimeout(resourceWaitTimer);
};
// 资源加载完毕
page.onResourceReceived = function (res) {
// chunk模式的HTTP回包,会多次触发resourceReceived事件,需要判断资源是否已经end
if (res.stage !== 'end'){
return;
}
resourceCount--;
if (resourceCount === 0){
// 当页面中全部资源都加载完毕后,截取当前渲染出来的html
// 由于onResourceReceived在资源加载完毕就立即被调用了,我们需要给一些时间让JS跑解析任务
// 这里默认预留500毫秒
resourceWaitTimer = setTimeout(capture, resourceWait);
}
};
// 资源加载超时
page.onResourceTimeout = function(req){
resouceCount--;
};
// 资源加载失败
page.onResourceError = function(err){
resourceCount--;
};
// 打开页面
page.open(url, function (status) {
if (status !== 'success') {
phantom.exit(1);
} else {
// 当改页面的初始html返回成功后,开启定时器
// 当到达最大时间(默认5秒)的时候,截取那一时刻渲染出来的html
maxWaitTimer = setTimeout(function(){
capture(2);
}, maxWait);
}
});
执行 phantomjs spider.js 'https://wj.qq.com/'
如果终端看到渲染后的HTML, 代表成功了
解析vue项目,app内容为空时解决方案
方案来源:https://www.cnblogs.com/tizi/p/13632573.html
空白原因:
浏览器不兼容ES6语法,需要将代码中的ES6语法通过插件的方式进行转换,而且由于babel会忽略node_modules,导致依赖包中的ES6语法无法被转换
- 安装相关插件
npm install babel-polyfill es6-promise --save
- main.js中引入,并配置 ( 注意:针对vue-cli2和vue-cli3,步骤一、步骤二相同,下面步骤有区分)
import 'babel-polyfill' import Es6Promise from 'es6-promise' require('es6-promise').polyfill() Es6Promise.polyfill()
-
vue-cli2项目 和 vue-cli3项目配置
-
vue-cli2项目配置
-
vue-cli2项目,创建一个.babelrc文件
{ "presets": [ "es2015" , "stage-2" ], "plugins": [ "transform-vue-jsx", "transform-runtime", ["import", [{ "libraryName": "vant", "style": true }]] ], }
-
vue-cli2项目,更改webpack.base.conf.js文件配置
const path = require('path') function resolve (dir) { return path.join(__dirname, '..', dir) } module.exports = { context: path.resolve(__dirname, '../'), entry: { app: ["babel-polyfill", "./src/main.js"] // app: './src/main.js' }, module: { rules: [ { test: /\.js$/, loader: 'babel-loader', // include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')] query: { presets: ['es2015'] }, include: [ resolve('src'), resolve('static/js'), resolve('test'), resolve('node_modules/webpack-dev-server/client'), resolve('node_modules/vant') ] }, ] } }
-
-
vue-cli3项目配置
-
vue-cli3项目,新建一个babel的配置文件,babel.config.js
var plugins = []; if (['production', 'prod'].includes(process.env.NODE_ENV)) { plugins.push("transform-remove-console") } module.exports = { presets: [ [ "@vue/app", { "useBuiltIns": "entry", polyfills: [ 'es6.promise', 'es6.symbol' ] } ] ], plugins: plugins } transform-remove-console是用来在打包之前删除控制台打印,不需要的可以去掉
-
vue-cli3项目,更改vue.config.js
const path = require('path'); function resolve(dir) { return path.join(__dirname, '.', dir); } module.exports = { ... // 其他配置 publicPath: process.env.NODE_ENV === "production" ? "./" : "./", // 默认情况下 babel-loader 会忽略所有 node_modules 中的文件。 // 如果你想要通过 Babel 显式转译一个依赖,可以在这个选项中列出来 transpileDependencies: [], chainWebpack: config => { config.module.rule('compile') .test(/\.js$/) .include .add(resolve('src')) .add(resolve('test')) .add(resolve('node_modules/webpack-dev-server/client')) .add(resolve('node_modules')) .end() .use('babel') .loader('babel-loader') .options({ presets: [ ['@babel/preset-env', { modules: false }] ] }); } }
f
-
-
适配好了可以用360兼容模式打开,看看页面是否有内容,有内容则适配成功
3.安装 express
- 全局安装express
npm install express -gd
- 安装express生成器
npm install -g express-generator
- 将express设置为全局
ln -s /opt/software/nodejs/bin/express /usr/bin/
4.创建 server.js
// server.js
// ExpressJS调用方式
var express = require('express');
// var phantomjs = require('phantom');
var app = express();
var path = process.cwd();
// 引入NodeJS的子进程模块
var child_process = require('child_process');
app.get('*', function(req, res){
// 部署到服务器的完整URL
var url = req.protocol + '://'+ req.hostname + req.originalUrl;
// 测试的url
// var url = 'https://www.baidu.com'
// 预渲染后的页面字符串容器
var content = '';
// 开启一个phantomjs子进程
var phantom = child_process.spawn('phantomjs', [path + '/spider.js', url]);
// 设置stdout字符编码
phantom.stdout.setEncoding('utf8');
// 监听phantomjs的stdout,并拼接起来
phantom.stdout.on('data', function(data){
content += data.toString();
});
// 监听子进程退出事件
phantom.on('exit', function(code){
console.log("content是:")
console.log(content)
switch (code){
case 1:
console.log('加载失败');
res.send('加载失败');
break;
case 2:
console.log('加载超时: '+ url);
res.send(content);
break;
default:
console.log('加载页面: '+ url);
res.send(content);
break;
}
});
});
app.listen(3001, function () {
console.log('Spider app listening on port3001!');
});
npm install express --save //安装一个express包
nohup node server.js &
注:运行 server.js 时,spider.js 要在同一个文件夹下面
5.nginx 配置
server {
listen 80;
server_name localhost;
location / {
proxy_set_header Host $host:$proxy_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
if ($http_user_agent ~* "Baiduspider|twitterbot|facebookexternalhit|rogerbot|linkedinbot|embedly|quora link preview|showyoubot|outbrain|pinterest|slackbot|vkShare|W3C_Validator|bingbot|Sosospider|Sogou Pic Spider|Googlebot|360Spider") {
proxy_pass http://localhost:3001;
}
root html;
index index.html index.htm;
}
}
以上就是vue phantomjs seo 优化全部内容