最新公告
  • 欢迎您光临网站无忧模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • vue-ssr(上)

    正文概述 掘金(超级肥的兔子)   2021-01-15   636

    vue-ssr(上)

    • spa全部靠的是js来渲染,默认首页显示内容是一个空的div标签,不利于SEO搜索引擎搜索

    • 服务端渲染是可以被爬虫抓取到的,客户端异步渲染是很难被爬虫抓取到的

    • spa应用会有首页白屏时间过长的问题,服务器渲染的好处是将访问好的数据拼接好给前端,首页白屏时间缩短

    需要占用服务器的CPU和内存,前端中的一些生命周期函数无法使用

    vue-ssr(上)

    vue-ssr使用

    vue 
    vue-server-renderer 
    koa
    koa-router
    

    template.html: 这里的 <!--vue-ssr-outlet--> 是固定字段

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    
    <body>
        <!--vue-ssr-outlet-->
    </body>
    
    </html>
    
    const Koa = require('koa');
    const Router = require('koa-router');
    const Vue = require('vue');
    const VueServerRenderer = require('vue-server-renderer');
    const app = new Koa();
    const router = new Router();
    const path = require('path');
    const fs = require('fs');
    
    const vm = new Vue({
        data: {
            name: '张三'
        },
        template: '<div>hello {{name}}</div>'
    })
    
    const template = fs.readFileSync(path.resolve(__dirname, 'template.html'), 'utf8');
    
    router.get('/', async (ctx) => {
        ctx.body = await VueServerRenderer.createRenderer(template).renderToString(vm);
    })
    //使用路由
    app.use(router.routes());
    app.listen(3000, () => {
        console.log('start server success')
    })
    

    通过webpack实现编译vue项目

    依赖包

    npm i webpack webpack-cli webpack-merge -D
    npm i @babel/core @babel/preset-env babel-loader -D
    npm i vue-loader vue-style-loader vue-template-compiler -D
    npm i css-loader html-webpack-plugin concurrently -D 
    

    项目结构

    ssr
    ├── dist
    │   ├── client.bundle.js
    │   ├── client.html
    │   ├── server.bundle.js
    │   └── server.html
    ├── package-lock.json
    ├── package.json
    ├── public
    │   ├── index.html
    │   └── index.ssr.html
    ├── server.js
    ├── src
    │   ├── App.vue
    │   ├── client-entry.js
    │   ├── components
    │   │   ├── Bar.vue
    │   │   └── Foo.vue
    │   ├── main.js
    │   └── server-entry.js
    ├── vue-ssr.md
    ├── webpack.base.js
    ├── webpack.client.js
    └── webpack.server.js
    

    公共webpack配置

    const VueLoaderPlugin = require('vue-loader/lib/plugin')
    module.exports = {
        mode: 'development',
        output: '[name].bundle.js',
        module: {
            rules: [{
                    test: /\.css$/,
                    use: ['vue-style-loader', {
                        loader: 'css-loader',
                        options: {
                            esModule: false, //注意配合vue-style-loader使用时需要加上这个属性
                        }
                    }]
                },
                {
                    test: /\.js$/,
                    use: {
                        loader: 'babel-loader',
                        options: {
                            presets: ['@babel/preset-env']
                        }
                    }
                },
                {
                    test: /\.vue$/,
                    use: 'vue-loader'
                }
            ]
        },
        plugins: [
            new VueLoaderPlugin() //
        ]
    }
    

    客户端webpack配置

    const path = require('path');
    cosnt HtmlWebpackPlugin = require('html-webpack-plugin');
    const {
        merge
    } = reqire('webpack-merge');
    const base = require('./webpack.base.js');
    module.exports = (base, {
        entry: {
            client: path.resolve(__dirname, './src/client-entry.js')
        },
        plugins: [
            new HtmlWebpackPlugin({
                template: path.resolve(__dirname, './public/index.html'),
                filename: 'client.html'
            })
        ]
    })
    

    服务端webpack配置

    const path = require('path');
    cosnt HtmlWebpackPlugin = require('html-webpack-plugin');
    const {
        merge
    } = reqire('webpack-merge');
    const base = require('./webpack.base.js');
    module.exports = merge(base, {
        target: 'node', //目标是给node使用
        entry: {
            server: path.resolve(__dirname, './src/server-entry.js')
        },
        output: {
            libraryTarget: 'commonjs2' //让打包后的server.bundle.js用module.exports导出
        },
        plugins: [
            new HtmlWebpackPlugin({
                template: path.resolve(__dirname, './public/index.ssr.html'),
                filename: 'server.html',
                excludeChunks: ['server'], //打包后server.html中不引入server.bundle.js
                mimyfy: false, //不压缩,防止<!--vue-ssr-outlet-->被覆盖
            })
        ]
    })
    

    index.ssr.html

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    
    <body>
        <!--vue-ssr-outlet-->
        <script src="./client.bundle.js"></script>
    </body>
    
    </html>
    

    index.html

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    
    <body>
        <div id="app"></div>
    </body>
    
    </html>
    

    main.js

    const Vue from 'vue';
    const App from './App.vue';
    
    export default () => {
        const app = new Vue({
            render: h => h(App)
        })
        return {
            app
        }
    }
    

    client-entry.js

    const createApp from './main.js';
    const {
        app
    } = createApp();
    app.$mount('#app');
    

    server-entry.js

    const createApp from './main.js';
    export default () => {
        const {
            app
        } = createApp();
        return app;
    }
    

    server.js

    const Koa = require('koa');
    const Router = require('koa-router');
    const static = require('koa-static');
    const VueServerRenderer = require('vue-server-renderer');
    const fs = require('fs');
    const path = require('path');
    
    const app = new Koa();
    cont router = new Router();
    
    const serverBundle = fs.readFileSync(path.resolve(__dirname, './dist/server.bundle.js'));
    const template = fs.readFileSync(path.resolve(__dirname, './dist/server.html'));
    const render = VueServerRenderer.createBundleRenderer(serverBundle, {
        template
    })
    
    router.get('/', async (ctx) => {
        ctx.body = new Promise((resolve, reject) => {
            render.renderToString((err, html) => {
                if (err) reject(err);
                resolve(html);
            })
        })
    })
    
    app.use(route.routes())
    app.use(static(path.resolve(__dirname, './dist')));
    app.listen(3000, () => {
        console.log('start server success');
    })
    

    App.vue

    <template>
      <div id='app'>
        <Foo></Foo>
        <Bar></Bar>
      </div>
    </template>
    
    <script>
    import Bar from "./components/Bar.vue";
    import Foo from "./components/Foo.vue";
    export default {
      components: {
        Foo,
        Bar,
      },
    };
    </script>
    

    Bar.vue

    <template>
        <div>bar</div>
    </template>
    
    <style scoped="true">
    div{
        background:red
    }
    </style>
    

    Foo.vue

    <template>
        <div @click="show">foo</div>
    </template>
    <script>
    export default {
        methods:{
            show(){
                alert(1)
            }
        }
    }
    </script>
    

    下载网 » vue-ssr(上)

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元