国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

接了個新項目

stormgens / 476人閱讀

摘要:背景最近接了個新項目,遇到一些問題,在這整理分享下。你可能要問,既然可以不用配為什么你還要用呢可能是因為,加個看起來比較丑吧未完待續(xù),持續(xù)更新目前處于階段,主要功能開發(fā)完成,計劃號上測試,進(jìn)度上問題不大。

背景
最近接了個新項目, 遇到一些問題, 在這整理分享下。

前期規(guī)劃

需求是這樣的,需要做一套后臺管理系統(tǒng): 一個主系統(tǒng),一個子系統(tǒng),開發(fā)時間6個周。 前期開發(fā)有兩個人, 再加一個人。

說實話時間有點緊, 所以前期做好規(guī)劃就很重要。 實現(xiàn)先做一個規(guī)劃,技術(shù)選型,文檔分析,分頁面, 有個大致的評估。

技術(shù)選型

首先確定的還是 React 這一套, 即: ReactReduxTypeScript, 樣式管理 styled-components, 國際化 react-intl, 組件庫 antd, 腳手架,自己配。 本來想圖省事用 CRA(create-react-app),后來覺得用rewired 重寫不太靈活, 而且有個小伙伴也想自己配,熟悉下 webpack , 還是決定自己搭, 后面會把配置貼出來。

開發(fā)計劃

和后端負(fù)責(zé)人討論之后決定把這一期的開發(fā)任務(wù)分成三個小階段: P1, P2, P3

P1 完成之后發(fā)布, 先跑通主流程,P2 P3 繼續(xù)迭代功能。

P1 主要包括:

開發(fā)環(huán)境搭建

test環(huán)境資源申請

Nginx 配置

主系統(tǒng)功能開發(fā)

三個功能模塊開發(fā)

登陸注冊流程

子系統(tǒng)兩個模塊的開發(fā)

開發(fā)時間: 兩周

壓力還是有的,時間緊,任務(wù)重,而且是第一次帶人做項目, 好在內(nèi)心猶如一條老狗,一點都不慌。

后面就進(jìn)入了開發(fā)階段, 遇到了挺多問題。

進(jìn)入開發(fā) 搭建開發(fā)環(huán)境

這一步大家就都很熟悉了,添加各種配置和打包。 因為主系統(tǒng)和子系統(tǒng)頁面風(fēng)格都是一樣的, 沒必要分成兩個系統(tǒng), 把新開一個文件夾,里面放子系統(tǒng)的頁面, 然后打成不同的包就可以了。就有了如下配置:

// webpack.config.js

const path = require("path")
const HtmlWebpackPlugin = require("html-webpack-plugin")
const webpack = require("webpack")
const fs = require("fs")
const lessToJS = require("less-vars-to-js")

const { NODE_ENV } = process.env

const isAdminApp = process.env.APP_TYPE === "admin"
const getBaseurl = () => {
  switch (process.env.ENV) {
    case "id":
      return "https://xxx.test.shopee.co.id"
    default:
      return ""
  }
}

const plugins = [
  new HtmlWebpackPlugin({
    template: path.resolve(__dirname, "template.html"),
    title: isAdminApp ? "WMS LITE ADMIN" : "WMS LITE",
  }),
  new webpack.DefinePlugin({
    __BASEURL__: JSON.stringify(getBaseurl()),
  }),
  new webpack.IgnorePlugin(/^./locale$/, /moment$/)
]
if (NODE_ENV !== "production") {
  plugins.push(new webpack.SourceMapDevToolPlugin({}))
}

const themeVariables = lessToJS(fs.readFileSync(path.resolve(__dirname, "./assets/antd-custom.less"), "utf8"))

const port = isAdminApp ? 9527 : 8080

module.exports = {
  entry: [
    "@babel/polyfill",
    isAdminApp ? "./admin/index.js" : "./pages/index.js"
  ],
  output: {
    filename: isAdminApp ? "admin.[hash:8].js" : "main.[hash:8].js",
    path: path.resolve(__dirname, isAdminApp ? "dist/adminstatic" : "dist/static"),
    publicPath: isAdminApp ? "/admin/" : "/",
  },
  mode: NODE_ENV,
  devtool: false,
  plugins,
  module: {
    rules: [
      {
        test: /.(js|jsx)$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader",
        },
      },
      {
        test: /.less$/,
        use: [
          { loader: "style-loader", },
          { loader: "css-loader", },
          {
            loader: "less-loader",
            options: {
              javascriptEnabled: true,
              sourceMap: true,
              modifyVars: themeVariables,
            },
          }
        ],
      },
      {
        test: /.css$/,
        use: [
          { loader: "style-loader", },
          { loader: "css-loader", }
        ],
      },
      {
        type: "javascript/auto",
        test: /.mjs$/,
        use: [],
      },
      {
        test: /.(png|jpg|gif|svg)$/i,
        use: [
          {
            loader: "url-loader",
            options: {
              limit: 8192,
            },
          }
        ],
      }
    ],
  },
  optimization: {
    runtimeChunk: {
      name: "manifest",
    },
    splitChunks: {
      chunks: "all",
      minSize: 30000,
      minChunks: 1,
      maxAsyncRequests: 5,
      maxInitialRequests: 3,
      cacheGroups: {
        vendor: {
          test: /[/]node_modules/,
          filename: "vendor.[chunkhash:8].js",
          enforce: true,
          priority: 5,
        },
        antd: {
          test: /[/]node_modules[/]antd[/]/,
          filename: "antd.[chunkhash:8].js",
          priority: 10,
        },
        antdIcons: {
          test: /[/]node_modules[/]@ant-design[/]/,
          filename: "antd-icons.[chunkhash:8].js",
          priority: 15,
        },
        styles: {
          test: /.(scss|css)$/,
          filename: "styles.[hash:8].css",
          minChunks: 1,
          reuseExistingChunk: true,
          enforce: true,
          priority: 20,
        },
      },
    },
  },
  devServer: {
    historyApiFallback: isAdminApp ? {
      rewrites: [{ from: /.*/g, to: "/admin/index.html", }],
    } : true,
    hot: true,
    port,
    proxy: [{
      context: ["/admin/api", "/api"],
      target: "https://gudangku.test.shopee.co.id",
      changeOrigin: true,
      onProxyRes(proxyRes, _, res) {
        const cookies = proxyRes.headers["set-cookie"] || []
        const re = /domain=[w.]+;/i
        const newCookie = cookies.map(cookie => cookie.replace(re, "Domain=localhost;"))
        res.writeHead(200, {
          ...proxyRes.headers,
          "set-cookie": newCookie,
        })
      },
    }],
  },
}
// package.json

  "scripts": {
    "start": "NODE_ENV=development APP_TYPE=main webpack-dev-server",
    "build": "NODE_ENV=production APP_TYPE=main webpack",
    "start:admin": "NODE_ENV=development APP_TYPE=admin webpack-dev-server",
    "build:admin": "NODE_ENV=production APP_TYPE=admin webpack",
    "lint": "eslint ./ --ext js",
    "i18n": "node i18n/index.js"
  },

根據(jù)不同的參數(shù)打包, 主系統(tǒng)打包到 dist/static, 子系統(tǒng)打包到dist/adminstatic.

解決完打包的問題, 還有另一個問題, 就是本地開發(fā)的時候需要配置代理。

目前比較通用的做法有:

devServer 配置 proxy

修改 host

Nginx 做反向代理

// 也可以說只有兩種。

我用的是1, 原因是比較靈活, 這個系統(tǒng)后面要發(fā)布到7個或者更多的國家, 改host 總歸是不太優(yōu)雅, 來回倒騰Nginx 又費時費力, 提個單大半天不批,不太方便。

后面又遇到的問題是登陸的時候需要請求一次csrftoken, 因為 domain 不匹配所以cookie 種不進(jìn)來, 所以就改了下配置,代碼見 devServer 部分,這個問題就解決了。

打包優(yōu)化

初步做了個優(yōu)化, 代碼分包, 這個系統(tǒng)antd 用的比較多,代碼體積, 和業(yè)務(wù)代碼打在一個包里明顯是不合適的,就簡單分了一下:

壓縮后總體積900K。

FCP 1s, 勉強還能接受, 后面有需要再做優(yōu)化。

國際化實現(xiàn)
國際化用的是`react-intl`, 用起來就很簡單了:

主要就兩種形式:

直接翻譯:

需要特殊傳, 比如 placeholder, Modal 的title等,如果直接用1 的方式會顯示一個[object Object] ,好在react-intl 提供了 injectIntl 方法可以解決這個問題:

 is a component which cannot be placed to placeholder which expects a raw String.

用法:

import {injectIntl} from "react-intl"; 

class TestComponent extends React.Component{
  render(){
    const { intl } = this.props;
    return (
        
    )
  }
}

export default injectIntl(TestComponent);

傳入的 id, 是你自己定義的,如果有翻譯平臺的話, 可以自己添加這些key:

在翻譯平臺完成翻譯后, 需要下載到本地, 需要手動下載, 感覺很麻煩, 于是我就寫了個腳本來自動下載, 翻譯平臺更新后, 執(zhí)行下 yarn i18n 就可以更新過來了:

頁面字段的替換就按上面的兩種方法, 純粹的體力活, 沒什么好說的。

Nginx 配置

功能開發(fā)完之后, 要發(fā)布到測試環(huán)境, 中間要配置Nginx, 我這有個配置平臺, 加配置之后提單, 自動部署。

配置的時候還是遇到一些問題的。

首先解決 index.html 訪問路徑的問題:

需要配置的路徑有:

/

/index.html

/admin

/admin/index.html

首先看 //index.html

還需要配置環(huán)境和地區(qū):

/admin/admin/index.html 也一樣的配置。

不過需要注意的是, //admin 需要配置 try_files :

/ :

/admin :

對應(yīng)生成的 conf 文件:

什么是try_files

從字面上理解就是嘗試文件,再結(jié)合環(huán)境理解就是嘗試讀取文件, 那是想讀取什么文件呢,讀取 靜態(tài)文件.

$uri, 這個是nginx的一個變量,存放著用戶訪問的地址. 比如:http://www.xxx.com/index.html, 那么$uri就是 /index.html

$uri/ 代表訪問的是一個目錄,比如:http://www.xxx.com/hello/test/, 那么$uri/就是 /hello/test/

完整的解釋就是:

try_files 去嘗試到網(wǎng)站目錄讀取用戶訪問的文件, 如果第一個變量存在,就直接返回;
不存在繼續(xù)讀取第二個變量,如果存在,直接返回;不存在直接跳轉(zhuǎn)到第三個參數(shù)上。

至于為什么要配try_files , 因為我們的路由是基于browserHistory的, 如果用 hashHistory 就不用配 try_files。 你可能要問, 既然 hashHistory 可以不用配 try_files, 為什么你還要用browserHistory 呢?

可能是因為, 加個/#/ 看起來比較丑吧 :)

未完待續(xù), 持續(xù)更新..

5.21 目前處于P3階段, 主要功能開發(fā)完成,計劃5.27號上測試,進(jìn)度上問題不大。 后面有什么值得分享的問題再說。

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

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/114666.html

相關(guān)文章

  • 了個項目

    摘要:背景最近接了個新項目,遇到一些問題,在這整理分享下。你可能要問,既然可以不用配為什么你還要用呢可能是因為,加個看起來比較丑吧未完待續(xù),持續(xù)更新目前處于階段,主要功能開發(fā)完成,計劃號上測試,進(jìn)度上問題不大。 背景 最近接了個新項目, 遇到一些問題, 在這整理分享下。 前期規(guī)劃 需求是這樣的,需要做一套后臺管理系統(tǒng): 一個主系統(tǒng),一個子系統(tǒng),開發(fā)時間6個周。 前期開發(fā)有兩個人, 再加...

    chaos_G 評論0 收藏0
  • 前端開發(fā)流程中一定要注意的5個點!

    摘要:作為一個老前端給新人們的一些關(guān)于開發(fā)流程上的建議拒絕和設(shè)計稿沒有封板就要求排期,和產(chǎn)品設(shè)計充分溝通。雙方還是要找到平衡點確保產(chǎn)品質(zhì)量和上線時間點的前提下,前端的開發(fā)難度和工作量是合理的。 作為一個老前端給新人們的一些關(guān)于開發(fā)流程上的建議 1. 拒絕PRD和設(shè)計稿沒有封板就要求排期,和產(chǎn)品設(shè)計充分溝通。 前端開發(fā)經(jīng)常會遇到這樣的情況,項目經(jīng)理莫名奇妙發(fā)了個會議邀請,然后一股腦把產(chǎn)品下階段...

    王晗 評論0 收藏0
  • 程序員如何在996之外獲得收入

    摘要:因為網(wǎng)站建設(shè)一般項目比較小,我一個人是可以完成前后端開發(fā)的,如果做成成品當(dāng)然得加上小蘇設(shè)計師。關(guān)鍵詞選擇因為面向的是單個城市業(yè)務(wù),在城市選擇上猶豫了不少時間,首先得是一個大城市,客戶量足,當(dāng)時我在北京,小蘇是在一個省會城市。 我技術(shù)之外的資本是零,如果你也是這樣,那這篇文章適合你! 這是我的故事之一,希望對你有啟發(fā)。如果你每天下班后就是躺在床上刷刷斗音,看看微博。但是又總想擺脫黑暗迷亂...

    siberiawolf 評論0 收藏0
  • 程序員如何在996之外獲得收入

    摘要:因為網(wǎng)站建設(shè)一般項目比較小,我一個人是可以完成前后端開發(fā)的,如果做成成品當(dāng)然得加上小蘇設(shè)計師。關(guān)鍵詞選擇因為面向的是單個城市業(yè)務(wù),在城市選擇上猶豫了不少時間,首先得是一個大城市,客戶量足,當(dāng)時我在北京,小蘇是在一個省會城市。 我技術(shù)之外的資本是零,如果你也是這樣,那這篇文章適合你! 這是我的故事之一,希望對你有啟發(fā)。如果你每天下班后就是躺在床上刷刷斗音,看看微博。但是又總想擺脫黑暗迷亂...

    TZLLOG 評論0 收藏0
  • 程序員如何在996之外獲得收入

    摘要:因為網(wǎng)站建設(shè)一般項目比較小,我一個人是可以完成前后端開發(fā)的,如果做成成品當(dāng)然得加上小蘇設(shè)計師。關(guān)鍵詞選擇因為面向的是單個城市業(yè)務(wù),在城市選擇上猶豫了不少時間,首先得是一個大城市,客戶量足,當(dāng)時我在北京,小蘇是在一個省會城市。 我技術(shù)之外的資本是零,如果你也是這樣,那這篇文章適合你! 這是我的故事之一,希望對你有啟發(fā)。如果你每天下班后就是躺在床上刷刷斗音,看看微博。但是又總想擺脫黑暗迷亂...

    YFan 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<