【问题标题】:isomorphic reactjs cdn assets同构 reactjs cdn 资产
【发布时间】:2016-06-13 12:03:18
【问题描述】:

所以我几乎完成了我的第一个(同构)ReactJS,当我们部署它时,完成build.js 有点慢。一个建议是使用 CDN 来分离资产获取(cdn0、cdn1、cdn2 ...),我想知道如何在我的站点中执行此操作。在本地我的结构是

- build/
- config/
  - webpack-development.config.js
  - webpack-production.config.js
- node_modules/
- package.json
- public/
  - assets/ // (this is where my assets are)
    - css/
    - img/
  - build.js
- README.md
- src/
- views/

我的index.ejs现在是这样的

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <base href="/" />
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"/>
    <link rel="shortcut icon" type="image/x-icon" href="assets/img/ico-a-brain.png" />
    <link rel="stylesheet" href="assets/css/normalize.css">
    <link rel="stylesheet" href="assets/css/all.css">
    <!-- bunch more assets here -->
  </head>

  <body>
    <script type="text/javascript">
      window.__INITIAL_STATE__ = <%- JSON.stringify(initialState) %>;
    </script>

    <div id="app"><%- markup %></div>
    <script src="build.js"></script>
  </body>
</html>

还有一些有图片的组件

import React from 'react';

export default class HiwComponent extends React.Component {
  render() {
    return (
      <main className="box-960 box-center"> 

        <h1 className="mt-64">How It Works</h1>

        <ul id="how">
          <li>
            <img src="assets/img/ico-how-time.svg" onError={() => { this.onerror=null; this.src='assets/img/ico-how-time.png' }} alt="Pick" />
            <p><b>Pick</b> a time</p>
          </li>
          <li>
            <img src="assets/img/ico-how-plane.svg" onError={() => { this.onerror=null; this.src='assets/img/ico-how-plane.png' }} alt="Send" />
            <p><b>Send</b> request</p>
          </li>
        </ul>
      </main>
    )
  }
}

如何开始更改它以使用 CDN?你们用一些包来处理它吗?基本上我认为它应该像在本地一样,它仍然会使用./assets/css/some.css./assets/img/some.jpg,而在生产中它可能看起来可能是http://cdn0.amazon.com/assets/css/some.csshttp://cdn1.amazon.com/assets/img/some.jpg

【问题讨论】:

  • 如果瓶颈是 build.js 的加载时间,那么您是否考虑过使用代码拆分来仅预先加载最少的功能并按需加载其余功能。
  • 什么是分码?这也可能有用。但现在它不是真正的build.js。我们现在可以在不同的 CDN 中展示大量资产。

标签: javascript reactjs webpack cdn


【解决方案1】:

更新 2:

如果您想用 cdn url 随机替换路径(根据您下面的问题),您可以轻松修改路径替换插件脚本以允许该功能。

我为您创建了一个基于path-replace-plugin source code 的快速示例

var fs = require('fs');
var fileExists = require('file-exists');
var loaderUtils = require('loader-utils');
var CDNs = [
  '//cdn0.amazon.com',
  '//cdn1.amazon.com',
  '//cdn2.amazon.com',
];

module.exports = function(source) {
this.cacheable && this.cacheable();
var options = loaderUtils.parseQuery(this.query);

    if (this.resourcePath.indexOf(options.path) > -1) {
        var cdn = CDNs[Math.floor(Math.random()*CDNs.length)];
        var newPath = this.resourcePath.replace(options.path, cdn + options.replacePath);
        if (fileExists(newPath)) {
            // Introduce file to webpack in order to make them watchable
            this.dependency(newPath);
            return fs.readFileSync(newPath);
        }
    }

    return source;
};

module.exports.raw = true;

更新:

更简单的方法是在 Webpack 中使用 path replace plugin。这样你就不必给你的 JS 代码增加任何复杂性了

module.exports = {
  module: {
    loaders: [
      {
        test: /\.(jpe?g|png|gif|svg)$/i,
        loader: 'path-replace?path=assets&replacePath=//cdn.amazon.com/assets'
      }
    ]
  }
};

我希望这会有所帮助。

--

(原答案)

如果您使用 Webpack,那么您的产品构建可以注入一个标志(变量),您可以在应用中使用该标志(变量)来了解您是在产品还是开发中。

即使这样:

new webpack.DefinePlugin({
  'process.env': {
    NODE_ENV: '"production"'
  },
  __DEV__: false,

现在您知道可以在自定义函数getImageUrl() 中使用它,您可以通过 JS 模块共享它。

environment.js

function getImageUrl() {
    return __DEV__ ? '/' : '//cdn.amazon.com/';
}

export const imgUrl = getImageUrl();

HiwComponent.js

import React from 'react';
import { imgUrl } from './environment';

export default class HiwComponent extends React.Component {
  render() {
    return (
      <main className="box-960 box-center"> 

        <h1 className="mt-64">How It Works</h1>

        <ul id="how">
          <li>
            <img src={`${imgUrl}assets/img/ico-how-time.svg`} onError={() => { this.onerror=null; this.src=`${imgUrl}assets/img/ico-how-time.png` }} alt="Pick" />
            <p><b>Pick</b> a time</p>
          </li>
          <li>
            <img src={`${imgUrl}assets/img/ico-how-plane.svg`} onError={() => { this.onerror=null; this.src=`${imgUrl}assets/img/ico-how-plane.png` }} alt="Send" />
            <p><b>Send</b> request</p>
          </li>
        </ul>
      </main>
    )
  }
}

【讨论】:

  • 我想我现在已经实现了类似的东西。我现在创建了一个&lt;ImgComponent file="..." /&gt; 来处理路径构建,例如当它位于/assets 的本地时,如果它是生产的,则执行cdn{0-3}.amazon.com/assets。我可以用path-replace-plugin 实现cdn{0-3}(随机或计算)吗?
  • 我添加了一个更新来反映这种情况。这只是一个例子,我敢打赌你可以根据自己的需要做得更好
  • 我明白了。然后我仍然会使用您答案的loaders 部分?我还没有尝试过这些。是这篇文章吗-webpack.github.io/docs/how-to-write-a-loader.html
  • 这是否也意味着它将使用相同的cdnX 链接进行编译?还没试过抱歉。
  • 你是对的。您仍然会使用加载器,只需将其指向您的自定义加载器。您可以将加载程序用于生产,而不是在开发中使用。
【解决方案2】:

如果您谈论的是 Javascript、CSS 和图像文件等静态资产,最好的解决方案是使用 CSS 管理图像。

建议不要在 webpack 配置中携带 CDN 域/路径,并在构建时将其连接到您的 reactjs 代码,如 grgur 建议:

<ul id="how">
  <li>
    <img src={`${imgUrl}assets/img/ico-how-time.svg`} onError={() => { this.onerror=null; this.src=`${imgUrl}assets/img/ico-how-time.png` }} alt="Pick" />
    <p><b>Pick</b> a time</p>
  </li>
  <li>
    <img src={`${imgUrl}assets/img/ico-how-plane.svg`} onError={() => { this.onerror=null; this.src=`${imgUrl}assets/img/ico-how-plane.png` }} alt="Send" />
    <p><b>Send</b> request</p>
  </li>
</ul>

我认为最好使用 CSS 来管理图片的绝对路径,假设您使用的是 SASS,并且您在 CDN 中的 assets 目录结构是这样的:

注意是同一个CDN (http://cdn0.amazon.com/)

还有some.css的内容:

.box-960 {
  .mt-64 {
    #how { // BTW, avoid using ID's for CSS
      .ico-how-time {
        background-image: url(../img/ico-how-time.svg);
      }
      .ico-how-plane {
        background-image: url(../img/ico-how-plane.svg);
      }
    }
  }
}

您将独立于域/CDN/文件夹引用图像,您需要在反应代码中进行的一项更改是使用 CSS 类而不是放置图像路径 + 名称:

<ul id="how">
  <li>
    <div className="ico-how-time" />
    <p><b>Pick</b> a time</p>
  </li>
  <li>
    <div className="ico-how-plane" />
    <p><b>Send</b> request</p>
  </li>
</ul>

此外,您还必须弄清楚图像的其余样式,以使其看起来像是在使用 IMG 标记,即高度、宽度等。

这就是我想到的。

【讨论】:

  • 这可以工作,但它可能会有很多变化,因为我只从另一个人那里获得我的资产(和 html)。另外,如果我可以将 cdn0 更改为其他的,例如 cdn1、2 和 3,那就更好了。
  • 是的,这在很大程度上取决于您分配资产的方式。
猜你喜欢
  • 1970-01-01
  • 2013-06-30
  • 2022-08-03
  • 1970-01-01
  • 2017-06-07
  • 1970-01-01
  • 2015-06-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多