Thứ ba, 14/03/2017 | 00:00 GMT+7

Kết xuất phía server cơ bản với Vue.js và Express


Kết xuất phía server (SSR) là một trong những thứ mà từ lâu đã được coi là một trong những điểm mạnh nhất của React , Angular 2+Vue 2 . Nó cho phép bạn hiển thị ứng dụng của bạn trên server , sau đó hydrat hóa chúng bằng phản ứng phía client sau khi tải trang, giúp tăng đáng kể khả năng phản hồi và cải thiện thời gian tải trang web .

Thật không may, nó không phải là thứ rõ ràng nhất để cài đặt và tài liệu để hiển thị ứng dụng Vue.js trên server được trải rộng ở một số nơi. Hy vọng rằng hướng dẫn này sẽ giúp làm sáng tỏ mọi thứ cho bạn. :)

Cài đặt

Ta sẽ bắt đầu với mẫu webpack-simple của vue-cli để cung cấp cho ta cơ sở chung để làm việc.

# Create the project
$ vue init webpack-simple vue-ssr-example
$ cd vue-ssr-example

# Install dependencies
$ yarn # (or npm install)

Ta cũng cần ba gói khác, express cho server , vue-server-render để hiển thị gói, được tạo bởi vue-ssr-webpack-plugin .

# Install with yarn ...
$ yarn add express vue-server-renderer
$ yarn add vue-ssr-webpack-plugin -D # Add this as a development dependency as we don't need it in production.

# ... or with NPM
$ npm install express vue-server-renderer
$ npm install vue-ssr-webpack-plugin -D

Chuẩn bị ứng dụng

Mẫu webpack-simple không có khả năng SSR ngay khi xuất xưởng. Có một số thứ ta sẽ phải cấu hình trước.

Điều đầu tiên cần làm là tạo một file mục nhập riêng cho server . Ngay bây giờ mục nhập khách hàng là trong main.js. Hãy sao chép nó và tạo main.server.js từ nó. Các sửa đổi khá đơn giản. Ta chỉ cần xóa tham chiếu el và trả lại ứng dụng ở dạng xuất mặc định.

src / main.server.js
import Vue from 'vue';
import App from './App.vue';

// Receives the context of the render call, returning a Promise resolution to the root Vue instance.
export default context => {
  return Promise.resolve(
    new Vue({
      render: h => h(App)
    })
  );
}

Ta cũng cần sửa đổi index.html một chút để chuẩn bị cho SSR.

Thay thế <div id = “app”> </div> bằng , như vậy:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>vue-ssr-example</title>
  </head>
  <body>
    <!--vue-ssr-outlet-->
    <script src="/dist/build.js"></script>
  </body>
</html>

Cấu hình Webpack

Bây giờ, ta cần một file cấu hình webpack riêng để hiển thị gói server . Sao chép webpack.config.js vào một file mới, webpack.server.config.js .

Có một số thay đổi mà ta cần thực hiện:

webpack.server.config.js
const path = require('path')
const webpack = require('webpack')
// Load the Vue SSR plugin. Don't forget this. :P
const VueSSRPlugin = require('vue-ssr-webpack-plugin')

module.exports = {
  // The target should be set to "node" to avoid packaging built-ins.
  target: 'node',
  // The entry should be our server entry file, not the default one.
  entry: './src/main.server.js',
  output: {
    path: path.resolve(__dirname, './dist'),
    publicPath: '/dist/',
    filename: 'build.js',
    // Outputs node-compatible modules instead of browser-compatible.
    libraryTarget: 'commonjs2'
  },
  module: {
    rules: [
      {
        test: /\.vue$/,
        loader: 'vue-loader',
        options: {
          loaders: {
          }
          // other vue-loader options go here
        }
      },
      {
        test: /\.js$/,
        loader: 'babel-loader',
        exclude: /node_modules/
      },
      {
        test: /\.(png|jpg|gif|svg)$/,
        loader: 'file-loader',
        options: {
          name: '[name].[ext]?[hash]'
        }
      }
    ]
  },
  resolve: {
    alias: {
      'vue$': 'vue/dist/vue.esm.js'
    }
  },
  // We can remove the devServer block.
  performance: {
    hints: false
  },
  // Avoids bundling external dependencies, so node can load them directly from node_modules/
  externals: Object.keys(require('./package.json').dependencies),
  devtool: 'source-map',
  // No need to put these behind a production env variable.
  plugins: [
    // Add the SSR plugin here.
    new VueSSRPlugin(),
    new webpack.DefinePlugin({
      'process.env': {
        NODE_ENV: '"production"'
      }
    }),
    new webpack.optimize.UglifyJsPlugin({
      sourceMap: true,
      compress: {
        warnings: false
      }
    }),
    new webpack.LoaderOptionsPlugin({
      minimize: true
    })
  ]
}

Xây dựng cấu hình

Để đơn giản hóa việc phát triển, hãy cập nhật các tập lệnh xây dựng trong package.json để xây dựng cả gói webpack client và server .

Thay thế tập lệnh xây dựng duy nhất bằng ba tập lệnh này. Việc sử dụng vẫn như cũ, nhưng giờ đây bạn có thể xây dựng các gói client hoặc server riêng lẻ với build: clientbuild: server , tương ứng.

package.json (một phần)
{
  ...
  "scripts": {
    ...
    "build": "npm run build:server && npm run build:client",
    "build:client": "cross-env NODE_ENV=production webpack --progress --hide-modules",
    "build:server": "cross-env NODE_ENV=production webpack --config webpack.server.config.js --progress --hide-modules"
  },
  ...
}

Tập lệnh server

Bây giờ, ta cần tập lệnh server để hiển thị ứng dụng.

server.js (một phần)
#!/usr/bin/env node

const fs = require('fs');
const express = require('express');
const { createBundleRenderer } = require('vue-server-renderer');

const bundleRenderer = createBundleRenderer(
  // Load the SSR bundle with require.
  require('./dist/vue-ssr-bundle.json'),
  {
    // Yes, I know, readFileSync is bad practice. It's just shorter to read here.
    template: fs.readFileSync('./index.html', 'utf-8')
  }
);

// Create the express app.
const app = express();

// Serve static assets from ./dist on the /dist route.
app.use('/dist', express.static('dist'));

// Render all other routes with the bundleRenderer.
app.get('*', (req, res) => {
  bundleRenderer
    // Renders directly to the response stream.
    // The argument is passed as "context" to main.server.js in the SSR bundle.
    .renderToStream({url: req.path})
    .pipe(res);
});

// Bind the app to this port.
app.listen(8080);

Chạy ứng dụng

Nếu mọi việc suôn sẻ, bạn có thể tạo gói và chạy server với:

# Build client and server bundles.
$ npm run build
# Run the HTTP server.
$ node ./server.js

Nếu bạn truy cập http: // localhost: 8080 , mọi thứ sẽ ... giống nhau. Tuy nhiên, nếu bạn tắt JavaScript, mọi thứ sẽ vẫn như cũ, vì ứng dụng đang được hiển thị trên server trước tiên.


Cảnh báo

  • Không thể thay đổi bất kỳ module nào được tải từ node_modules thay vì gói qua các yêu cầu, (tức là có trạng thái toàn cục.) Nếu không, bạn sẽ nhận được kết quả không nhất quán khi hiển thị ứng dụng của bạn .
  • Đảm bảo rằng bạn viết các bảng của bạn đúng cách (bao gồm các phần tử shell bọc thead và / hoặc tbody .) Phiên bản phía client có thể phát hiện những vấn đề này, nhưng version phía server thì không thể, điều này có thể dẫn đến sự mâu thuẫn hydrat hóa.

Vòng thưởng

  • Hãy thử làm cho ứng dụng hiển thị một cái gì đó khác nhau tùy thuộc vào việc nó được hiển thị trên client hay server . Gợi ý: Bạn có thể chuyển đạo cụ cho Ứng dụng từ chức năng kết xuất root .
  • Đồng bộ trạng thái Vuex từ server đến client . Nó có thể liên quan đến một số biến toàn cục!

Tài liệu tham khảo


Tags:

Các tin liên quan

Cách thiết lập server VPN IKEv2 với StrongSwan trên Ubuntu 16.04
2017-02-17
Cách cấu hình firewall Linux cho Docker Swarm trên CentOS 7
2017-01-11
Cách cấu hình firewall Linux cho Docker Swarm trên Ubuntu 16.04
2017-01-09
Cách cài đặt Linux, Nginx, MySQL, PHP (LEMP Stack) trên Debian 8
2016-12-20
Cách thiết lập xác thực Linux tập trung với FreeIPA trên CentOS 7
2016-12-15
Cách bảo vệ server của bạn chống lại lỗ hổng Linux COW bẩn
2016-10-31
Cách cấu hình TRIM định kỳ cho bộ lưu trữ SSD trên server Linux
2016-08-25
Cách bảo vệ server của bạn chống lại lỗ hổng HTTPoxy
2016-07-18
Cách phân vùng và định dạng thiết bị lưu trữ trong Linux
2016-07-13
Cách thực hiện các tác vụ quản trị cơ bản cho thiết bị lưu trữ trong Linux
2016-07-13