說明
玩轉webpack學習筆記
webpack ssr 打包存在的問題
1、浏覽器的全局變量 (Node.js 中沒有 document, window)
- 元件适配:将不相容的元件根據打包環境進⾏适配
- 請求适配:将 fetch 或者 ajax 發送請求的寫法改成
或者 axiosisomorphic-fetch
2、樣式問題 (Node.js ⽆法解析 css)
- ⽅案⼀:服務端打包通過
忽略掉 CSS 的解析ignore-loader
- ⽅案⼆:将
替換成style-loader
isomorphic-style-loader
如何解決樣式不顯示的問題?
使⽤打包出來的浏覽器端 html 為模闆
設定占位符,動态插⼊元件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="root"><!--HTML_PLACEHOLDER--></div>
</body>
</html>
首屏資料如何處理?
服務端擷取資料
替換占位符
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="root"><!--HTML_PLACEHOLDER--></div>
<!--INITIAL_DATA_PLACEHOLDER-->
</body>
</html>
實作
由于上一節我已經将
如何解決樣式不顯示的問題?
這個問題已經處理,這一節就簡單實作
首屏資料如何處理?
1、在上一節的基礎上添加
<!--INITIAL_DATA_PLACEHOLDER-->
占位符
<!DOCTYPE html>
<html lang="en">
<head>
<%= require('raw-loader!./meta.html') %>
<title>Document</title>
<script><%= require('raw-loader!babel-loader!../../node_modules/lib-flexible/flexible.js') %></script>
</head>
<body>
<div id="root"><!--HTML_PLACEHOLDER--></div>
<script type="text/javascript" src="https://11.url.cn/now/lib/16.2.0/react.min.js"></script>
<script type="text/javascript" src="https://11.url.cn/now/lib/16.2.0/react-dom.min.js"></script>
<!--INITIAL_DATA_PLACEHOLDER-->
</body>
</html>
2、在server檔案夾裡添加 data.json 檔案,然後在server檔案夾的 index.js 裡引入
data.json
{
"error": [],
"extra": [],
"data": {
"list": [
[{
"sub_count": 5556,
"column_type": 1,
"id": 192,
"column_price_market": 9900,
"column_bgcolor": "#F6F7FB",
"column_title": "SQL必知必會",
"column_cover_small": "https:\/\/static001.geekbang.org\/resource\/image\/1c\/38\/1c5a5b154b543af952312eef33217438.jpg",
"column_cover": "https:\/\/static001.geekbang.org\/resource\/image\/c7\/0d\/c7ee0aabbcb6d2da09a1b4a56c1a730d.jpg",
"had_sub": false,
"price_type": 2,
"column_unit": "45講",
"is_experience": false,
"column_ctime": 1559640855,
"update_frequency": "每周一 \/ 三 \/ 五更新",
"is_onboard": true,
"author_intro": "清華大學計算機博士",
"column_sku": 100029501,
"column_cover_wxlite": "https:\/\/static001.geekbang.org\/resource\/image\/cd\/f0\/cd26b744d388dbd4387dcfaa66dd8bf0.jpg",
"column_price": 6800,
"column_price_sale": 6800,
"author_name": "陳旸",
"column_subtitle": "從入門到資料實戰"
}]
],
"nav": [{
"id": 1,
"name": "專欄",
"color": "#5ba6ff",
"icon": "https:\/\/static001.geekbang.org\/resource\/image\/dd\/9e\/dd8cbc79f017d1b01f643c7ea929d79e.png"
}, {
"id": 3,
"name": "視訊課程",
"color": "#79c109",
"icon": "https:\/\/static001.geekbang.org\/resource\/image\/4a\/c3\/4aebe8fb752fa21a0fd989a45d9847c3.png"
}, {
"id": 2,
"name": "微課",
"color": "#5ba6ff",
"icon": "https:\/\/static001.geekbang.org\/resource\/image\/9c\/f1\/9c223ccae33c5245a3009857582f1df1.png"
}]
},
"code": 0
}
index.js
if (typeof window === 'undefined') {
global.window = {};
}
const fs = require('fs');
const path = require('path');
const express = require('express');
const { renderToString } = require('react-dom/server');
const SSR = require('../dist/search-server');
const template = fs.readFileSync(path.join(__dirname, '../dist/search.html'), 'utf-8');
const data = require('./data.json'); // 引入資料
const renderMarkup = (str) => {
const dataStr = JSON.stringify(data);
return template.replace('<!--HTML_PLACEHOLDER-->', str)
.replace('<!--INITIAL_DATA_PLACEHOLDER-->', `<script>window.__initial_data=${dataStr}</script>`);
};
const server = (port) => {
const app = express();
app.use(express.static('dist'));
app.get('/search', (req, res) => {
console.log('SSR-----------》', SSR);
console.log('renderToString(SSR)------>', renderToString(SSR));
const html = renderMarkup(renderToString(SSR));
res.status(200).send(html);
});
app.listen(port, () => {
console.log(`Server is running on port:${port}`);
});
};
server(process.env.PORT || 3000);