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

Các khóa học qua video:
Python SQL Server PHP C# Lập trình C Java HTML5-CSS3-JavaScript
Học trên YouTube <76K/tháng. Đăng ký Hội viên
Viết nhanh hơn - Học tốt hơn
Giải phóng thời gian, khai phóng năng lực

Chúng ta sẽ giả sử bạn đã biết cách cấu hình webpack cho một dự án chỉ dành cho client. Cấu hình cho một dự án SSR sẽ phần lớn tương tự, nhưng chúng tôi khuyên bạn nên chia cấu hình thành ba tệp: baseclient và server. Cấu hình base chứa cấu hình được chia sẻ cho cả hai môi trường, chẳng hạn như đường dẫn đầu ra, bí danh và trình tải. Cấu hình server và cấu hình client có thể đơn giản mở rộng cấu hình base bằng cách sử dụng webpack-merge.

Cấu hình server

Cấu hình server có nghĩa là tạo gói máy chủ sẽ được chuyển đến createBundleRenderer. Nó sẽ giống như thế này:

const merge = require('webpack-merge')
const nodeExternals = require('webpack-node-externals')
const baseConfig = require('./webpack.base.config.js')
const VueSSRServerPlugin = require('vue-server-renderer/server-plugin')

module.exports = merge(baseConfig, {
  // Điểm đầu vào tới file đầu vào server của app của bạn
  entry: '/path/to/entry-server.js',

  // Điều này cho phép xử lý các import động trong một thể hiện node riêng biệt
  // , và cũng cho `vue-loader` biết cần phát ra mã lệnh hướng server khi
  // biên dịch các component Vue.
  target: 'node',

  // Trình kết xuất gói hỗ trợ source map
  devtool: 'source-map',

  // Nó sẽ chỉ cho gói server sử dụng node-style để xuất
  output: {
    libraryTarget: 'commonjs2'
  },

  // https://webpack.js.org/configuration/externals/#function
  // https://github.com/liady/webpack-node-externals
  // Các dependency ngoài app. Điều này sẽ giúp cho việc build server nhanh hơn nhiều và
  // tạo ra một gói file nhỏ hơn.
  externals: nodeExternals({
    // không có dependency ngoài nào cần phải được xử lý bởi webpack.
    // bạn có thể thêm nhiều loại file ở đây, ví dụ các tệp *.vue
    // bạn cũng nên lập danh sách trắng các dependency thay đổi `global` (ví dụ như polyfill)
    whitelist: /\.css$/
  }),

  // Đây là plugin trả toàn bộ output của server build
  // vào một file JSON. Tên file mặc định sẽ là
  // `vue-ssr-server-bundle.json`
  plugins: [
    new VueSSRServerPlugin()
  ]
})

Sau khi vue-ssr-server-bundle.json được tạo, chỉ cần chuyển đường dẫn tệp tới createBundleRenderer:

const { createBundleRenderer } = require('vue-server-renderer')
const renderer = createBundleRenderer('/path/to/vue-ssr-server-bundle.json', {
  // ...các tùy chọn kết xuất khác
})

Ngoài ra, bạn cũng có thể truyền gói như một đối tượng đến createBundleRenderer. Điều này rất hữu ích cho việc tải lại trong quá trình phát triển - xem bản demo HackerNews để thiết lập tham chiếu.

#External Caveat

Lưu ý rằng trong tùy chọn externals là các tệp CSS danh sách trắng. Điều này là do CSS được import từ các dependency vẫn nên được xử lý bởi webpack. Nếu bạn đang import bất kỳ loại file khác cũng dựa vào webpack (ví dụ *.vue*.sass), bạn nên thêm chúng vào danh sách trắng.

Nếu bạn đang sử dụng runInNewContext: 'once' hoặc runInNewContext: true, thì bạn cũng cần phải lập danh sách trắng polyfills sửa đổi global, ví dụ babel-polyfill. Điều này là do khi sử dụng chế độ ngữ cảnh mới, mã bên trong một gói máy chủ có globalđối tượng riêng của nó . Vì bạn không thực sự cần nó trên máy chủ khi sử dụng Node 7.6+, nó thực sự dễ dàng hơn để chỉ cần nhập nó vào mục nhập của máy khách.

Cấu hình ứng dụng khách

Cấu hình máy khách có thể vẫn giữ nguyên với cấu hình cơ bản. Rõ ràng bạn cần trỏ entry đến tệp mục nhập ứng dụng của bạn. Ngoài ra, nếu bạn đang sử dụng CommonsChunkPlugin, hãy đảm bảo chỉ sử dụng nó trong cấu hình máy khách vì gói máy chủ yêu cầu một mục nhập duy nhất.

tạoclientManifest

# Đa

yêu cầu phiên bản 2.3.0+

Ngoài gói máy chủ, chúng ta cũng có thể tạo tệp kê khai xây dựng ứng dụng khách. Với tệp kê khai của khách hàng và gói máy chủ, trình kết xuất giờ đây có thông tin về cả máy chủ  máy khách, vì vậy nó có thể tự động suy ra và chèn các chỉ thị nạp trước/tìm nạp trước và các liên kết css/thẻ script vào HTML được hiển thị.

Các lợi ích đôi:

  1. Nó có thể thay thế html-webpack-plugin cho việc đưa vào các nội dung URL chính xác khi có băm trong tên tệp được tạo của bạn.

  2. Khi kết xuất một gói để tận dụng các tính năng chia nhỏ mã theo yêu cầu của webpack, chúng ta có thể đảm bảo các khối tối ưu được tải trước/được nạp trước và cũng cung cấp thẻ <script> thông minh cho các khối async cần thiết để tránh yêu cầu dạng thác nước trên máy khách, do đó cải thiện TTI (time-to-interactive).

Để sử dụng tệp kê khai của client, cấu hình máy khách sẽ trông giống như sau:

const webpack = require('webpack')
const merge = require('webpack-merge')
const baseConfig = require('./webpack.base.config.js')
const VueSSRClientPlugin = require('vue-server-renderer/client-plugin')

module.exports = merge(baseConfig, {
  entry: '/path/to/entry-client.js',
  plugins: [
    // Important: this splits the webpack runtime into a leading chunk
    // so that async chunks can be injected right after it.
    // this also enables better caching for your app/vendor code.
    new webpack.optimize.CommonsChunkPlugin({
      name: "manifest",
      minChunks: Infinity
    }),
    // This plugins generates `vue-ssr-client-manifest.json` in the
    // output directory.
    new VueSSRClientPlugin()
  ]
})

Sau đó, bạn có thể sử dụng tệp kê khai của client được tạo, cùng với mẫu trang:

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

const template = require('fs').readFileSync('/path/to/template.html', 'utf-8')
const serverBundle = require('/path/to/vue-ssr-server-bundle.json')
const clientManifest = require('/path/to/vue-ssr-client-manifest.json')

const renderer = createBundleRenderer(serverBundle, {
  template,
  clientManifest
})

Với thiết lập này, HTML được máy chủ trả về của bạn cho một bản build có tính năng chia mã sẽ trông giống như sau (mọi thứ được tự động chèn):

<html>
  <head>
    <!-- chunks used for this render will be preloaded -->
    <link rel="preload" href="/manifest.js" as="script">
    <link rel="preload" href="/main.js" as="script">
    <link rel="preload" href="/0.js" as="script">
    <!-- unused async chunks will be prefetched (lower priority) -->
    <link rel="prefetch" href="/1.js" as="script">
  </head>
  <body>
    <!-- app content -->
    <div data-server-rendered="true"><div>async</div></div>
    <!-- manifest chunk should be first -->
    <script src="/manifest.js"></script>
    <!-- async chunks injected before main chunk -->
    <script src="/0.js"></script>
    <script src="/main.js"></script>
  </body>
</html>

#Tách nội dung thủ công

Theo mặc định, tính năng chèn nội dung là tự động khi bạn cung cấp tùy chọn hiển thị template. Nhưng đôi khi bạn có thể muốn kiểm soát chi tiết hơn về cách nội dung được đưa vào template, hoặc có thể bạn không sử dụng template nào cả. Trong trường hợp này, bạn có thể chuyển inject: false khi tạo trình kết xuất và thực hiện thao tác chèn nội dung theo cách thủ công.

Trong callback renderToString, đối tượng context bạn truyền vào sẽ hiển thị các phương thức sau:

  • context.renderStyles()

    Điều này sẽ trả về các thẻ inline <style> chứa tất cả CSS quan trọng được thu thập từ các component *.vue được sử dụng trong quá trình hiển thị. Xem Quản lý CSS để biết thêm chi tiết.

    Nếu clientManifest được cung cấp, chuỗi được trả lại cũng sẽ chứa các thẻ <link rel="stylesheet"> cho các tệp CSS được phát tán trên webpack (ví dụ: CSS được trích xuất bằng extract-text-webpack-plugin hoặc được nhập với file-loader)

  • context.renderState(options?: Object)

    Phương thức này tuần tự hóa context.state và trả về một tập lệnh inline nhúng trạng thái là window.__INITIAL_STATE__.

    Khóa trạng thái ngữ cảnh và khóa trạng thái cửa sổ có thể được tùy chỉnh bằng cách truyền một đối tượng tùy chọn:

    context.renderState({
      contextKey: 'myCustomState',
      windowKey: '__MY_STATE__'
    })
    
    // -> <script>window.__MY_STATE__={...}</script>
    
  • context.renderScripts()

    • yêu cầu clientManifest

    Phương thức này trả về các thẻ <script> cần thiết cho ứng dụng máy khách để khởi động. Khi dùng biện pháp tách mã không đồng bộ trong mã ứng dụng, phương thức này sẽ suy ra các khối async chính xác một cách thông minh để đưa vào.

  • context.renderResourceHints()

    • yêu cầu clientManifest

    Phương thức này trả về các <link rel="preload/prefetch"> gợi ý tài nguyên cần thiết cho trang được hiển thị hiện tại. Theo mặc định, nó sẽ:

    • Tải trước các tệp JavaScript và CSS cần thiết bởi trang
    • Tìm nạp trước các đoạn mã JavaScript không đồng bộ mà có thể cần sau này

    Các tệp được tải sẵn có thể được tùy chỉnh thêm với tùy chọn shouldPreload.

  • context.getPreloadFiles()

    • yêu cầu clientManifest

    Phương thức này không trả về một chuỗi - thay vào đó, nó trả về một mảng các đối tượng tệp đại diện cho các phần tử cần được tải trước. Điều này có thể được sử dụng để lập trình thực hiện đẩy máy chủ HTTP/2.

Vì template truyền đến createBundleRenderer sẽ được nội suy bằng cách sử dụng context, nên bạn có thể sử dụng các phương thức này bên trong template (với inject: false):

<html>
  <head>
    <!-- dùng cặp ngoặc xoắn cho nội suy non-HTML-escaped -->
    {{{ renderResourceHints() }}}
    {{{ renderStyles() }}}
  </head>
  <body>
    <!--vue-ssr-outlet-->
    {{{ renderState() }}}
    {{{ renderScripts() }}}
  </body>
</html>

Nếu bạn không sử dụng template, bạn có thể tự nối các chuỗi.

» Tiếp: Quản lý CSS
« Trước: Giới thiệu Trình kết xuất gói
Các khóa học qua video:
Python SQL Server PHP C# Lập trình C Java HTML5-CSS3-JavaScript
Học trên YouTube <76K/tháng. Đăng ký Hội viên
Viết nhanh hơn - Học tốt hơn
Giải phóng thời gian, khai phóng năng lực
Copied !!!