成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

【全棧React】第27天: 部署介紹

kyanag / 1427人閱讀

摘要:本文轉載自眾成翻譯譯者鏈接原文今天,我們將探討部署我們的應用所涉及的不同部分,以便外界可以使用我們的應用。今天我們將專注于讓我們的應用準備好部署。將一切視為一個模塊包括像這樣的圖像資產(chǎn)。在本章的其余部分我們將討論這一權力的各個方面。

本文轉載自:眾成翻譯
譯者:iOSDevLog
鏈接:http://www.zcfy.cc/article/3803
原文:https://www.fullstackreact.com/30-days-of-react/day-27/

今天,我們將探討部署我們的應用所涉及的不同部分,以便外界可以使用我們的應用。

我們的應用通過這一點進行了測試, 現(xiàn)在是時候讓它起來為世界而活。本課程的其余部分將致力于將我們的應用部署到生產(chǎn)中。

生產(chǎn)部署

在談到部署時, 我們有很多不同的選擇:

主機

部署環(huán)境配置

持續(xù)集成 (簡稱 CI)

成本周期、網(wǎng)絡帶寬成本

包大小

更多

我們將看看不同的托管選項, 明天看看部署我們的react應用的一些不同的方法, 我們部署我們的應用。今天, 我們將專注于讓我們的應用準備好部署。

彈出 (從create-react-app)

首先, 我們需要在 web 應用中處理一些自定義, 所以我們需要在目錄的根中運行 npm run eject 命令。這是一個永久性的動作,現(xiàn)在這只是意味著我們將負責處理我們的應用結構的自定義 (沒有我們的方便create-react-app的幫助)。

這是我 總是 說, 做一個備份副本的應用。我們不能從 ejecting返回, 但我們可以恢復到舊代碼。

我們可以通過運行由create-react-app結構生成器提供的彈出命令來 _彈出_:

npm run eject

ejectingcreate-react-app結構中, 我們將看到我們的應用根目錄中有很多新文件在config/scripts/ 目錄。npm run eject 命令創(chuàng)建了它在內部使用的所有文件, 并在我們的應用中為我們編寫了所有的文檔。

create-react-app`生成器的關鍵方法稱為webpack, 它是一個模塊打包器/生成器。

webpack 基礎知識

Webpack 是一個大社區(qū)的用戶模塊打包器, 成噸的插件正在積極開發(fā), 有一個聰明的插件系統(tǒng), 是令人難以置信的快速, 支持熱代碼重裝, 和更多的多。

雖然我們沒有真正調用它之前, 我們一直在使用 webpack 這整個時間 (在npm start 的幌子下)。如果沒有 webpack, 我們就不可能只寫import , 并期望我們的代碼加載。它的工作原理像這樣, 因為 webpack "看到"import 的關鍵字, 并且知道我們需要在應用運行時可以訪問路徑上的代碼。

Webpack 為我們照顧熱加載, 幾乎自動, 可以加載和打包許多類型的文件包, 它可以以邏輯方式拆分代碼, 以便支持延遲加載和收縮用戶的初始下載大小。

這對我們是有意義的, 因為我們的應用越來越大, 更復雜, 重要的是要知道如何操縱我們的構建工具。

例如, 當我們要部署到不同的環(huán)境..。首先, 對 webpack 的一個微小的介紹, 它是什么以及它是如何工作的。

bundle.js做什么

當我們運行 npm start 查看生成的文件之前我們彈出的應用,我們可以看到它為瀏覽器服務兩個或更多的文件。第一個是index.htmlbundle.js.。webpack 服務器負責將bundle.js.插入index.html , 即使我們不在index.html 文件中加載我們的應用。

bundle.js 文件是一個巨大的文件, 包含我們的應用需要運行的 所有 的 JavaScript 代碼, 包括依賴和我們自己的文件。Webpack 有它自己的方法包裝文件在一起, 所以當看原始的源碼它看起來有點有趣。

Webpack 已經(jīng)對所有包含的 JavaScript 進行了一些轉換。值得注意的是, 它使用Babel以 ES5-compatible 的格式轉換我們的 ES6 代碼, 。

如果您查看 app.js,的注釋頭, 它有一個數(shù)字 "254":

/* 254 */
/*!********************!*
  !*** ./src/app.js ***!
  ********************/

模塊本身封裝在一個類似如下的函數(shù)中:

function(module, exports, __webpack_require__) {
  // The chaotic `app.js` code here
}

我們的 web 應用的每個模塊都用這個簽名封裝在一個函數(shù)里面。Webpack 已經(jīng)給我們的每個應用的模塊這個功能容器以及模塊 ID (在app.js的情況下, 254)。

但是這里的 "模塊" 不限于 ES6 模塊。

Remember how we "imported" the makeRoutes() function in app.js, like this:請記住, 我們是如何在app.js"導入" makeRoutes()函數(shù)的, 如下所示:

import makeRoutes from "./routes"

這里的變量聲明的makeRoutes 看起來像在混亂的app.js Webpack 模塊:

var _logo = __webpack_require__(/*! ./src/routes.js */ 255);

他看起來很奇怪, 主要是因為 Webpack 為調試目的提供的在線評論。刪除該注釋:

var _logo = __webpack_require__(255);

我們有簡單的舊 ES5 代碼, 而不是import 語句。

現(xiàn)在, 在這個文件中搜索./src/routes.js 。

/* 255 */
/*!**********************!*
  !*** ./src/routes.js ***!
  **********************/

請注意, 它的模塊 ID 是 "255", 相同的整數(shù)傳遞給上面的 __webpack_require__。

Webpack 將 一切 視為一個模塊, 包括像logo.svg這樣的圖像資產(chǎn)。我們可以通過在logo.svg模塊的混亂中挑選出一條路徑來了解發(fā)生了什么。您的路徑可能不同, 但它看起來像這樣:

static/media/logo.5d5d9eef.svg

如果您打開一個新的瀏覽器標簽并插入這個地址 (您的地址將是不同的... 匹配為您生成的文件 webpack 的名稱):

http://localhost:3000/static/media/logo.5d5d9eef.svg

你應該得到的React Logo:

因此, Webpack 為 logo.svg 創(chuàng)建了一個 Webpack 模塊, 它指的是 Webpack 開發(fā)服務器上的 svg 路徑。由于這種模塊化范例, 它能夠智能地編譯如下語句:

import makeRoutes from "./routes"

進入這 ES5 聲明:

var _makeRoutes = __webpack_require__(255);

我們的 CSS 資產(chǎn)呢?是的, 一切 是 Webpack 的一個模塊。搜索字符串./src/app.css:

Webpack 的index.html 沒有包含任何對 CSS 的引用。這是因為 Webpack 是通過bundle.js包括我們的 CSS 在這里。當我們的應用加載時, 這個神秘的 Webpack 模塊函數(shù)將app.css 的內容轉儲到頁面上的style 標簽中。

因此, 我們知道 _什么 正在發(fā)生: Webpack 已經(jīng)卷起每一個可以想象的 "模塊" 為我們的應用進入bundle.js "。你可能會問: 為什么?

第一個動機是普遍的 JavaScript 包。Webpack 已經(jīng)將我們所有的 ES6 模塊轉換為自己定制的 ES5-兼容 模塊語法。正如我們簡要介紹的, 它將我們所有的 JavaScript 模塊封裝在特殊功能中。它提供了一個模塊 ID 系統(tǒng), 使一個模塊能夠引用另一個。

Webpack 和其他打包器一樣, 將我們所有的 JavaScript 模塊整合到一個文件中。它 可能 將 JavaScript 模塊放在多帶帶的文件中, 但是這需要比create-react-app提供更多的配置。

然而, Webpack 比其他打包器更重視這個模塊范例。正如我們所看到的, 它適用于圖像資產(chǎn), CSS 和 npm 包 (如React和 ReactDOM) 相同的模塊化處理。這種模塊化范式釋放了大量的力量。在本章的其余部分, 我們將討論這一權力的各個方面。

復雜, 對不對?

如果你不明白這一點沒關系建立和維護 webpack 是一個復雜的項目, 有大量的移動部件, 它往往需要即使是最有經(jīng)驗的開發(fā)商而 "得到"。

我們將遍歷我們將使用我們的 webpack 配置的不同部分,。如果它感覺壓倒性, 只是堅持我們的基礎上, 其余的將遵循。

隨著我們對 Webpack 內部運作的新認識, 讓我們把注意力轉向我們的應用。我們將對我們的 webpack 構建工具進行一些修改, 以支持多種環(huán)境配置。

環(huán)境配置

當我們準備好部署一個新的應用時, 我們必須考慮一些我們在開發(fā)應用時不必關注的事情。

例如, 假設我們正在請求 api 服務器的數(shù)據(jù)...... 在開發(fā)此應用時, 我們可能會在本地計算機上運行 API 服務器的開發(fā)實例 (可通過localhost訪問)。

當我們部署應用時, 我們希望從外部主機請求數(shù)據(jù), 很可能不在發(fā)送代碼的位置上, 所以localhost 只是不能做到。

我們能夠處理配置管理的一種方法是使用 .env文件 。這些 .env 文件將包含不同的變量, 為我們不同的條件, 但仍然提供了我們處理配置的正常方式的一種方式,。

通常情況下, 我們將在根目錄中保留一個.env 文件, 以包含一個 全局 配置, 可以在每個基礎上按條件將其重寫。

讓我們安裝一個稱為dotenvnpm 程序包, 以幫助我們進行此配置設置,

npm install --save-dev dotenv

dotenv 庫幫助我們將環(huán)境變量加載到我們的環(huán)境中的應用的 ENV 中。

添加 .env 到我們的.gitignore 文件通常是一個好主意, 所以我們不簽入這些設置。

傳統(tǒng)上, 創(chuàng)建一個 .env 文件的示例版本是一個好主意,。例如, 對于我們的應用, 我們可以創(chuàng)建一個名為.env.example的必須變量。

稍后, 另一個開發(fā)人員 (或我們, 幾個月后) 可以使用 .env.example 文件作為.env文件應該是什么樣的模板。

這些.env 文件可以包含變量, 就好像它們是 unix 樣式的變量一樣。讓我們創(chuàng)建一個全局的變量APP_NAME 設置為30days:

touch .env
echo "APP_NAME=30days" > .env

讓我們?yōu)g覽到爆炸的config/ 目錄, 在那里我們將看到為我們寫的我們所有的構建工具。我們不會查看所有這些文件, 但是為了了解 什么 的情況, 我們將開始查找config/webpack.config.dev.js。

此文件顯示了用于構建我們的應用的所有 webpack 配置。它包括裝載、插件、入口點等。對于我們當前的任務, 要查找的行是在 plugins 列表中定義 DefinePlugin():

module.exports = {
  // ...
  plugins: [
    // ...
    // Makes some environment variables available to 
    // the JS code, for example:
    // if (process.env.NODE_ENV === "development") {
    //  ... 
    // }. See `env.js` 
    new webpack.DefinePlugin(env),
    // ...
  ]
}

webpack.DefinePlugin 插件采用了一個帶有 "鍵" 和 "值" 的對象, 并在我們的代碼中找到了我們使用"鍵"的所有位置, 并將它替換為值。

例如, 如果 env 對象看起來像:

{
  "__NODE_ENV__": "development"
}

我們可以在我們的源使用變量__NODE_ENV__ , 它將被替換為 "development", 即:

class SomeComponent extends React.Component {
  render() {
    return (
      
Hello from {__NODE_ENV__}
) } }

render()函數(shù)的結果會說 "Hello from development"。

要將我們自己的變量添加到我們的應用中, 我們將使用這個env 對象, 并添加我們自己的定義。向上滾動到文件頂部, 我們將看到它當前是從 config/env.js 文件中創(chuàng)建和導出的。

看著 config/env.js 文件, 我們可以看到, 它將所有的變量都放在我們環(huán)境, 并將NODE_ENV添加到環(huán)境中, 以及任何以 REACT_APP_為前綴的變量。

// ...
module.exports = Object
  .keys(process.env)
  .filter(key => REACT_APP.test(key))
  .reduce((env, key) => {
    env["process.env." + key] = JSON.stringify(process.env[key]);
    return env;
  }, {
    "process.env.NODE_ENV": NODE_ENV
  });

我們可以跳過該操作的所有復雜部分, 因為我們只需要修改第二個參數(shù)以減少函數(shù), 換句話說, 我們將更新對象:

{
  "process.env.NODE_ENV": NODE_ENV
}

該對象是歸并函數(shù)的_初始_對象。reduce函數(shù)將所有以REACT_APP_為前綴的變量_合并_到此對象中,所以我們總是在我們的源代碼中替換process.env.NODE_ENV 。

基本上我們要做的是:

加載我們的默認.env文件

加載任何環(huán)境的.env文件

將這兩個變量以及任何默認變量(如NODE_ENV)合并在一起

我們將創(chuàng)建一個包含所有環(huán)境變量的新對象,并對每個值進行清理。

更新現(xiàn)有環(huán)境創(chuàng)建者的初始對象。

讓我們忙吧 為了加載.env文件,我們需要導入dotenv包。 我們還將從標準節(jié)點庫導入path庫,并為路徑設置一些變量。

Let"s update the config/env.js file我們來更新config / env.js文件

var REACT_APP = /^REACT_APP_/i;
var NODE_ENV = process.env.NODE_ENV || "development";

const path = require("path"),
      resolve = path.resolve,
      join = path.join;

const currentDir = resolve(__dirname);
const rootDir = join(currentDir, "..");

const dotenv = require("dotenv");

要加載全局環(huán)境,我們將使用dotenv庫公開的config() 函數(shù),并傳遞根目錄中加載的.env文件的路徑。 我們還將使用相同的功能在config/目錄中查找名稱為NODE_ENV.config.env.的文件。 此外,我們不希望這些方法之一出錯,所以我們將添加一個silent: true 的附加選項,以便如果找不到該文件,則不會拋出異常。

// 1. Step one (loading the default .env file)
const globalDotEnv = dotenv.config({
  path: join(rootDir, ".env"),
  silent: true
});
// 2. Load the environment config
const envDotEnv = dotenv.config({
  path: join(currentDir, NODE_ENV + `.config.env`),
  silent: true
});

接下來, 讓我們將所有這些變量串聯(lián)在一起, 并在這個對象中包括我們的 NODE_ENV 選項。Object.assign() 方法創(chuàng)建一個 對象, 并從右向左合并每個對象。這樣, 環(huán)境配置變量

const allVars = Object.assign({}, {
  "NODE_ENV": NODE_ENV
}, globalDotEnv, envDotEnv);

使用當前的設置, allVars 變量的外觀將如下所:

{
  "NODE_ENV": "development",
  "APP_NAME": "30days"
}

最后, 讓我們創(chuàng)建一個將這些變量放在 process.env 中的對象, 并確保它們是有效的字符串 (使用JSON.stringify)。

const initialVariableObject =
  Object.keys(allVars)
  .reduce((memo, key) => {
    memo["process.env." + key.toUpperCase()] = 
      JSON.stringify(allVars[key]);
    return memo;
  }, {});

使用我們當前的設置(在根目錄中有.env文件),這將創(chuàng)建initialVariableObject 為以下對象:

{
  "process.env.NODE_ENV": ""development"",
  "process.env.APP_NAME": ""30days""
}

現(xiàn)在, 我們可以使用這個 initialVariableObject 作為原始module.exports 的第二個參數(shù)。讓我們更新它以使用這個對象:

module.exports = Object
  .keys(process.env)
  .filter(key => REACT_APP.test(key))
  .reduce((env, key) => {
    env["process.env." + key] = JSON.stringify(process.env[key]);
    return env;
  }, initialVariableObject);

現(xiàn)在, 我們的代碼中的任何位置都可以使用我們在 .env 文件中設置的變量。

由于我們正在向我們的應用中的離線站點發(fā)出請求, 讓我們使用我們的新配置選項來更新此主機。

假設默認情況下, 我們希望將 TIME_SERVER 設置為 http://localhost:3001,這樣, 如果在環(huán)境配置中不設置TIME_SERVER ,它將默認為本地主機。我們可以通過將TIME_SERVER 變量添加到全局 "。

讓我們更新 .env 文件, 使其包括此時間服務器:

APP_NAME=30days
TIME_SERVER="http://localhost:3001"

現(xiàn)在, 我們已經(jīng)開發(fā)的 "開發(fā)" 與服務器托管在 heroku。我們可以設置我們的config/development.config.env 文件, 以設置 TIME_SERVER 變量, 它將覆蓋全局項:

TIME_SERVER="https://fullstacktime.herokuapp.com"

現(xiàn)在, 當我們運行npm start時, 任何出現(xiàn)的process.env.TIME_SERVER 將被替換為優(yōu)先值。

讓我們更新我們的src/redux/modules/currentTime.js 模塊來使用新的服務器, 而不是我們以前使用的硬編碼的。

// ...
export const reducer = (state = initialState, action) => {
  // ...
}

const host = process.env.TIME_SERVER;
export const actions = {
  updateTime: ({timezone = "pst", str="now"}) => ({
    type: types.FETCH_NEW_TIME,
    meta: {
      type: "api",
      url: host + "/" + timezone + "/" + str + ".json",
      method: "GET"
    }
  })
}

現(xiàn)在, 對于我們的生產(chǎn)部署, 我們將使用 heroku 應用, 因此, 讓我們在config/下創(chuàng)建development.config.env 的一份拷貝為production.config.env 。

cp config/development.config.env config/production.config.env
每個配置環(huán)境自定義中間件

我們在應用中使用了自定義日志再現(xiàn)中間件。這對于在我們的開發(fā)站點上工作是非常棒的, 但是我們并不希望它在生產(chǎn)環(huán)境中處于活動狀態(tài)。

讓我們更新我們的中間件配置, 在開發(fā)時只使用日志中間件, 而不是在所有環(huán)境中。在我們的項目的src/redux/configureStore.js 文件中, 我們用一個簡單的數(shù)組加載了我們的中間件:

let middleware = [
  loggingMiddleware,
  apiMiddleware
];
const store = createStore(reducer, applyMiddleware(...middleware));

現(xiàn)在, 我們在我們的文件中有了 process.env.NODE_ENV , 我們可以更新middleware 數(shù)組, 這取決于我們正在運行的環(huán)境。讓我們更新它, 如果我們在開發(fā)環(huán)境中只添加日志記錄,:

let middleware = [apiMiddleware];
if ("development" === process.env.NODE_ENV) {
  middleware.unshift(loggingMiddleware);
}

const store = createStore(reducer, applyMiddleware(...middleware));

現(xiàn)在, 當我們運行應用的開發(fā), 我們將有loggingMiddleware 設置, 而在任何其他環(huán)境中, 我們已經(jīng)禁用它。

今天是一個漫長的, 但明天是一個激動人心的一天, 因為我們將得到應用和運行在遠程服務器上。

今天的工作很棒, 明天見!

文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉載請注明本文地址:http://m.hztianpu.com/yun/87212.html

相關文章

  • 全棧ReactReact 30教程索引

    摘要:今天我們將討論創(chuàng)建組件的最終方案,即無狀態(tài)函數(shù)的純組件。今天我們正在研究一種處理提出的復雜數(shù)據(jù)的方法,稱為體系結構。第天部署介紹今天,我們將探討部署我們的應用所涉及的不同部分,以便外界可以使用我們的應用。 本文轉載自:眾成翻譯譯者:iOSDevLog鏈接:http://www.zcfy.cc/article/3758原文:https://www.fullstackreact.com/3...

    appetizerio 評論0 收藏0
  • 全棧React29: 持續(xù)集成

    摘要:本文轉載自眾成翻譯譯者鏈接原文今天,我們將介紹一些可持續(xù)的集成解決方案,為我們提供運行測試以及實施測試我們在云端的應用。我們已經(jīng)啟動了一個測試套件但是現(xiàn)在我們要確保它在部署之前完全通過。 本文轉載自:眾成翻譯譯者:iOSDevLog鏈接:http://www.zcfy.cc/article/3801原文:https://www.fullstackreact.com/30-days-of...

    xavier 評論0 收藏0
  • 全棧React28: 部署

    摘要:本文轉載自眾成翻譯譯者鏈接原文今天,我們將看看一些即將推出的選項,以便我們的網(wǎng)站啟動并運行。昨天我們離開了準備第一次部署我們的應用程序?,F(xiàn)在的問題是我們要在哪里和如何部署讓我們來探索什么這與部署非頁應用程序類似。 本文轉載自:眾成翻譯譯者:iOSDevLog鏈接:http://www.zcfy.cc/article/3802原文:https://www.fullstackreact.c...

    liuhh 評論0 收藏0
  • 全棧React22: 測試簡介

    摘要:我們將討論三種不同的軟件測試范例單元測試功能測試和集成測試。在中單元測試通常不需要瀏覽器可以快速運行不需要寫入斷言本身通常是簡單而簡潔的。集成測試最后我們將研究的最后一種測試是集成測試。 本文轉載自:眾成翻譯譯者:iOSDevLog鏈接:http://www.zcfy.cc/article/3809原文:https://www.fullstackreact.com/30-days-of...

    qc1iu 評論0 收藏0
  • 全棧React12: 創(chuàng)建React應用

    摘要:本文轉載自眾成翻譯譯者鏈接原文今天,我們將添加一個構建過程來存儲常見的構建操作,以便我們可以輕松地開發(fā)和部署我們的應用。在要創(chuàng)建應用的目錄中打開終端窗口。文件有一個的節(jié)點,這個應用本身將被自動掛載這是在文件中處理的。 本文轉載自:眾成翻譯譯者:iOSDevLog鏈接:http://www.zcfy.cc/article/3822原文:https://www.fullstackreact...

    solocoder 評論0 收藏0

發(fā)表評論

0條評論

閱讀需要支付1元查看
<