Сводка личной сборки для корпоративных проектов React

внешний интерфейс JavaScript React.js Webpack

предисловие

Прошло много времени с последней статьи.В последние две недели компания была отправлена ​​в BOE в командировку, чтобы отвечать за предварительную работу устоявшейся проектной команды. За это время я построил front-end проект с нуля, в этот раз уделял больше времени и больше думал. В прошлом были интерфейсные проекты, но времени было относительно мало, поэтому многие проблемы были проигнорированы. На этот раз мы просто оптимизировали предыдущую и подытожили некоторые впечатления, чтобы поделиться с вами. Если у вас есть лучшие идеи, пожалуйста, оставьте сообщение для обмена.

Советы:

  • Этот проект основан на перспективах проекта интерфейса ПК, и проект мобильного интерфейса не полностью применим. Вы, ребята, должны обратить на это внимание.

  • Проект велся в разных направлениях, и соответствующее направление каждой ветки можно найти вCONTRIBUTING.mdПосмотреть в

инструкция проекта

адрес проекта: https://github.com/ruichengping/react-webpack-pc

Проект можно собрать с помощью написанного мной инструмента asuna-cli.Адрес инструмента, написанного мной, следующий:

https://github.com/ruichengping/asuna-cli


项目结构

Выше приведена структура каталогов примера проекта, мы проанализируем ее по порядку ниже**

build

Этот файл в основном содержит некоторые связанные файлы, упакованные с помощью webpack.

  • build.js---- сценарий упаковки веб-пакета, используемый для сборки пакета рабочей среды
  • check-versions.js---- В основном определяет, соответствует ли версия узла и npm текущей среды упаковки требованиям.
  • utils.js---- Некоторые библиотеки инструментов, необходимые для упаковки веб-пакетов
  • webpack.base.conf.js---- Некоторые базовые конфигурации webpack, конфигурации webpack различных сред основаны на этом
  • webpack.dev.conf.js---- конфигурация веб-пакета для среды разработки
  • webpack.prod.conf.js---- конфигурация веб-пакета для производственной среды

Я изменил конфигурацию веб-пакета этого проекта в проекте vue-cli, который можно использовать для создания проекта React. В настоящее время существует только две среды: среда разработки и производственная среда.Некоторые компании могут иметь несколько сред, и конфигурация веб-пакета в каждой среде отличается.В настоящее время формат имени файла может быть создан в соответствии с различными средами. .webpack..conf.js'' конфигурация веб-пакета для использования.webpack.base.conf.jsЕсть несколько основных конфигураций, таких какrules,input,outputконфигурации, вообще говоря, они примерно одинаковы в каждой среде, и можно использовать некоторые различияwebpack-mergeПлагины объединены. Вообще говоря, для большинства проектов достаточно двух конфигураций веб-пакета для среды разработки и рабочей среды.

config

Здесь хранятся параметры конфигурации, необходимые веб-пакету в различных средах.

  • dev.env.js---- Предоставить переменные среды в среде разработки для внешнего мираNODE_ENV
  • index.js---- Сохраняет параметры конфигурации для различных сред
  • prod.env.js---- Предоставить переменные среды в производственной среде снаружиNODE_ENV

Если вам нужно добавить другую среду, вы можете создать файл с именем «.env.js» и открыть переменные среды для внешнего мира.NODE_ENV, а затем импортируйте его в index.js, чтобы задать соответствующие параметры.

mock

Это для издевательства над интерфейсом, который может не использоваться многими компаниями, а я редко хожу на издевательство на работе. Вот введение в мои собственные идеи насмешек над интерфейсом, здесь я выбираюmockjsплюсjson-serverКомбинация. Для конкретного использования этих двух вы можете проверить их официальные документы.

  • api---- Храните данные, соответствующие различным API
  • index.js---- Основной файл json-сервера
  • routes.json---- отображение маршрутизации

package.json я настраиваю скрипт следующим образом:

 "mock": "json-server mock/index.js  --port 3000 --routes mock/routes.json"

Консоль выполняет «npm run mock».

src

api

url.js

export default {
  fetchUserInfo:{
    method:'get',
    url:'/api/user'
  },
  fetchAuthorInfo:{
    method:'get',
    url:'/api/author'
  },
  fetchUserList:{
    method:'get',
    url:'/api/userList'
  }
}

index.js

import _ from 'lodash'
import http from '@/utils/http'
import API_URL from './url';

function mapUrlObjToFuncObj(urlObj){
  const API = {};
  _.keys(urlObj).forEach((key)=>{
    const item = urlObj[key]
    API[key]=function(params){
      return http[item.method](item.url,params)
    }
  });
  return API;
}

function mapUrlObjToStrObj(urlObj){
  const Url = {};
  _.keys(urlObj).forEach((key)=>{
    const item = urlObj[key]
    Url[key]=item.url
  });
  return Url;
}

export const API = mapUrlObjToFuncObj(API_URL);
export const URL = mapUrlObjToStrObj(API_URL);

Здесь мы используем для размещения адреса интерфейса апи, для последующего обслуживания интерфейса мы не будем напрямую прописывать мертвый адрес интерфейса в процессе использования, а инкапсулируем запрос интерфейса в один метод. За счет унифицированного обслуживания интерфейса мы можем добиться того, что при выполнении таких операций, как изменение адреса интерфейса, изменение метода запроса, добавление интерфейса и т. д., нет необходимости искать повсюду во всем проекте, пока поддерживается внешний объект url.js. Способ применения следующий:

import {API} from '@/api'
//params为请求参数
API.fetchUserInfo(params).then(response=>{
    //response为返回值
    ...
})

assets

Здесь мы поместим ресурсы изображений, необходимые для проекта.Эти ресурсы изображений обычно используются в качестве значков и относительно невелики. webpack преобразует его вBASE64использовать. Если вы не хотите использовать его таким образом, вы можете хранить ресурсы изображения в статическом каталоге.

components

Здесь хранятся общедоступные компоненты, используемые всем проектом. Чтобы определить компонент, требуется создать новую папку, имя папки — это имя компонента, а в этой папке создаются файлы index.jsx и style.scss. Например, чтобы сделать компонент HelloWorld, он должен иметь следующую структуру.

HelloWorld

  • index.jsx
  • style.scss //Сохраняем стиль компонента

index.js

import React from 'react';
import './style.scss';
class HelloWorld extends React.PureComponent{
  render(){
    return (
      <h4 className="u-text">Hello World</h4>
    )
  }
}
export default HelloWorld;

style.scss

.u-text{
  color: red;
}

layouts

这里存放着布局文件。关于这个布局文件我是这么去定义它的,我在开发过程中有一些页面他们的某一部分都是相同,早之前可能大家可能会在一个React组件加和去实现这个功能,可以这么干,没毛病。但是这个有一个不好点就是你的路由没法做统一的管理,分散在各个组件中,给后续的维护带来很多问题。为了解决这个,我选择利用props.children结合标签嵌套的方式去完成。 Например:

Сначала установите макет (это тоже компонент React) BasicLayout.jsx

import React from 'react';
class BasicLayout extends React.PureComponent{
    render(){
        const {children} = this.props;
        return (
            <div>
                <div>隔壁老王今日行程:</div>
                <div>{children}</div>
            </div>
        )
    }
}
export default BasicLayout;

После определения мы можем использовать его следующим образом:

import React from 'react';
import BasicLayout from '<BasicLayout的路径>'
class Work extends React.PureComponent{
    render(){
        return (
            <BasicLayout>
                <div>今天隔壁老王比较累,不工作!</div>
            <BasicLayout>
        )
    }
}
export default BasicLayout;

Окончательная структура DOM выглядит следующим образом:

<div>
    <div>隔壁老王今日行程:</div>
    <div>
        <div>今天隔壁老王比较累,不工作!</div>
    </div> 
</div>

Таким образом, мы можем создать множество страниц, подобных приведенным ниже, на основе BasicLayout.

<div>
    <div>隔壁老王今日行程:</div>
    <div>
       //<不同的内容>
    </div> 
</div>

Используя этот метод, мы можем написать все наши маршруты вместе. Некоторые люди могут подумать, что каждый раз писать и импортировать BasicLayout очень хлопотно. Есть ли другой лучший способ? Я расскажу об этом здесь, когда буду говорить о App.jsx. Пропустить первым.

pages

Компоненты, хранящиеся здесь, являются компонентами уровня страницы, а маршруты, соответствующие react-router, должны соответствовать друг другу. Каждая страница — это папка, имя файла — это имя страницы, и каждая страница должна содержать следующие файлы:

  • компоненты ---- хранят некоторые компоненты, уникальные для текущей страницы
  • redux ---- хранить три файлаactions.js,actionTypes.js,reducer.js, эти файлы должны относиться только к этой странице
  • index.jsx ---- файл входа на страницу
  • style.scss -- стиль, требуемый страницей Конкретный код можно просмотреть самостоятельно в проекте клонирования git, и он не будет опубликован здесь.

scss

Здесь хранятся общие файлы scss, и сравниваются некоторые часто используемые функциональные классы, @mixin, @function и т. д.

store

Здесь четыре файла:

  • actions.js
  • actionTypes.js
  • reducer.js
  • index.js

Мы знаем, что у каждой страницы есть свойactions.js,actionTypes.js,reducer.js, но это глобально, и index.js выставит хранилище наружу, а затем введет его в main.js.

import {createStore,combineReducers,applyMiddleware} from 'redux';
import thunk from 'redux-thunk';
import API from '@/api';
import user from './reducer';
import author from '@/pages/PageOne/redux/reducer';
const rootReducer = combineReducers({
    user,
    author
  });
const store=createStore(
  rootReducer,
  applyMiddleware(thunk.withExtraArgument({
    API
  }))
)
export default store;

Вот небольшая деталь, redux-thunk может нести какие-то дополнительные объекты или методы, здесь я несу объект API. Когда нам нужно использовать объекты API в action.js, нам не нужно их импортировать. Давайте проведем сравнение:

перед фиксацией

import * as actionTypes from './actionTypes';
import API from '../api';

export const fecthUserName=(params)=> async (dispatch,getState)=>{
  const response =await API.fetchUserInfo(params);
  const {success,data} = response;
  if(success){
    dispatch({
      type:actionTypes.CHANGE_USER_NAME,
      payload:data
    });
  }
}

после модификации

import * as actionTypes from './actionTypes';

export const fecthUserName=(params)=> async (dispatch,getState,{API})=>{
  const response =await API.fetchUserInfo(params);
  const {success,data} = response;
  if(success){
    dispatch({
      type:actionTypes.CHANGE_USER_NAME,
      payload:data
    });
  }
}

utils

Здесь будут храниться некоторые из моих собственных инкапсулированных файлов инструментов js.Например, я инкапсулировал в проект http.js на основе axios, что упрощает работу с axios.

router/index.js

Здесь он настроен на предотвращение регистрации маршрутов и отображение меток маршрутов в app.js.

import Loadable from 'react-loadable';
import createHistory from 'history/createBrowserHistory';
import BasicLayout from '@/layouts/BasicLayout';
import NavTwoLayout from '@/layouts/NavTwoLayout';
import Loading from '@/components/Loading';
import NotFound from '@/pages/Exception/404';


const Home = Loadable({loader: () => import('@/pages/Home'),loading: Loading});
const Teachers = Loadable({loader: () => import('@/pages/Teachers'),loading: Loading});

export const history = createHistory();

export const routes = [
  {
    path:'/',
    redirect:'/navone/home'
  },
  {
    path:'/navone',
    redirect:'/navone/home',
    children:[{
      path:'/home',
      layout:BasicLayout,
      component:Home
    }]
  },
  {
    path:'/navtwo',
    redirect:'/navtwo/teachers',
    children:[{
      path:'/teachers',
      layout:NavTwoLayout,
      component:Teachers
    }]
  },
  {
    path:'*',
    component:NotFound
  }
]

App.js

Здесь используется для отображения метки маршрутизации в соответствии с конфигурацией маршрутизации, сначала поместите код:

import React from 'react';
import {Router} from 'react-router-dom';
import {Switch, Route ,Redirect} from 'react-router';
import {history,routes} from '@/router';



function getRouterByRoutes(routes){
  const renderedRoutesList = [];
  const renderRoutes = (routes,parentPath)=>{
    Array.isArray(routes)&&routes.forEach((route)=>{
      const {path,redirect,children,layout,component} = route;
      if(redirect){
        renderedRoutesList.push(<Redirect key={`${parentPath}${path}`} exact from={path} to={`${parentPath}${redirect}`}/>)
      }
      if(component){
        renderedRoutesList.push(
          layout?<Route 
            key={`${parentPath}${path}`} 
            exact path={`${parentPath}${path}`}
            render={(props)=>React.createElement(layout,props,React.createElement(component,props))} />:
          <Route 
              key={`${parentPath}${path}`} 
              exact 
              path={`${parentPath}${path}`} 
              component={component}/>)
      }
      if(Array.isArray(children)&&children.length>0){
        renderRoutes(children,path)
      }
    });
  }  
  renderRoutes(routes,'')
  return renderedRoutesList;
 
}
class App extends React.PureComponent{
  render(){
    return (
      <Router history={history}>
        <Switch>
          {getRouterByRoutes(routes)}
        </Switch>
      </Router>
    )
  }
}
export default App;

Здесь нам нужно сосредоточиться на содержимом, которое мы пропускаем в макете. Можем ли мы каждый раз оборачивать код компонентом макета? Ответ — да. Здесь я выбираю свойство рендеринга в.

main.js

Файл записи веб-пакета в основном импортирует некоторые глобальные js или scss и выполняет метод рендеринга под реактивным домом.Код выглядит следующим образом:

import React from 'react';
import {render} from 'react-dom';
import {Provider} from 'react-redux';
import store from '@/store';
import App from '@/App';
import '@/scss/reset.scss';
import '@/scss/base.scss';


render(
  <Provider store={store}>
    <App/>
  </Provider>,
  document.getElementById('app')
)

static

Это статический каталог ресурсов, обычно хранящий некоторые сторонние библиотеки инструментов. Этот каталог в основном рассматривает два аспекта:

  • Некоторые сторонние библиотеки инструментов не имеют пакетов npm, и мы не можем добавить их с помощью npm install или yarn add.
  • Некоторые относительно большие сторонние библиотеки инструментов повлияют на нашу скорость упаковки, мы можем взять их и импортировать через скрипт.

На самом деле лучший способ для сторонней библиотеки инструментов — это CDN, но у некоторых компаний ее просто нет, поэтому они могут сделать только это. Добавленная вами третья библиотека инструментов доступна на текущем сервере"/static/*", который нужно получить по пути.

templates

Файлы шаблонов, необходимые для построения на уровне страницы и компонента, хранятся здесь.Создание на уровне страницы предоставляет два шаблона: PageReducer (интегрированный редуктор) и PageSample (редуктор не интегрирован), в то время как компоненты предоставляют только один шаблон, ComSample. Конструкцию на уровне страниц и компонентов необходимо создавать с помощью asuna-cli.В настоящее время проект интегрирован с asuna-cli. package.json написал два скрипта: npm run newPage (сборка страницы) и npm run newComponent (сборка компонента). Разработка может выбрать сборку в соответствии с фактическими потребностями, конкретное использование asuna-cli может пойти наhttps://github.com/ruichengping/asuna-cliПроверить.

Другие файлы

  • .babelrc ---- файл конфигурации для преобразования Babel
  • .gitignore ---- файлы, которые необходимо игнорировать для операций git
  • .postcssrc.js ---- файл конфигурации postcss
  • index.html ---- шаблон index.html, веб-пакет сгенерирует новый index.html на основе этого, сотрудничайте сhtml-webpack-pluginиспользовать
  • package.json — имя нарицательное
  • Readme.md ---- Описание предмета
  • theme.js ---- файл конфигурации цвета темы ant-design, пожалуйста, обратитесь к ant-design для конкретного использования
  • asuna.config.js ---- файл конфигурации asuna-cli
  • yarn.lock ---- заблокировать версию пакета

Эпилог

Это просто краткое изложение личных проектов React корпоративного уровня. Конечно, есть недостатки, и если в процессе работы будут какие-то хорошие идеи, я обновлю его по этому поводу. Приглашаем всех обратить внимание на Звезду! Если у вас также есть хорошие идеи, оставьте сообщение для обмена, я надеюсь, что эта скромная статья вдохновит вас.