Создайте каркас React + Mobx + React Router с нуля

React.js

В этой статье подробно рассказывается, как создать основу для разработки React с нуля, в том числе как добавить Redux и React Router в среду.

Кодовый адрес этой статьи:react-mobx-starter.

Рекомендуется извлечь код и просмотреть его вместе с этой статьей для получения лучших результатов.

Команда загрузки кода:

git clone -b example https://github.com/beichensky/react-mobx-starter.git

Конфигурация babel в скаффолдинге недавно обновилась до версии 7.0.0, поэтому были внесены некоторые изменения. Текущие версии различных библиотек в скаффолдинге следующие:

  • узел: 10.15.3
  • нпм: 6.4.1
  • webpack: 4.29.6
  • webpack-cli: 3.3.0
  • webpack-dev-server: 3.1.4
  • @babel/core: 7.0.0
  • react: 16.8.6
  • mobx: 5.9.4
  • react-router-dom: 5.0.0

Если вы обновляетесь с более ранней версии до7.0.0версии официальный предоставляет новую команду, которая может напрямую помочь нам обновить проект:

npx babel-upgrade --write --install

больше оbabel-upgradeВведение может относиться кОфициальное описание.


1. Введение

этой статьиDemoРазделены на две среды: одна — среда разработки, а другая — производственная среда.

  • Среда разработки описывает, как настроить более качественную и удобную среду разработки;

  • В производственной среде описывается, как настроить более оптимизированную и уменьшенную версию производственной среды.

я простоWebpackНаписано несколько статей об использованииWebpackОснованный на разработке, он также является расширением предыдущего кода.

Предложение: для тех, кто еще не знаком с Webpack, вы можете сначала взглянутьСоздание конфигурации среды разработки Webpack с нуля (с демонстрацией)а такжеИспользуйте Webpack для настройки производственной среды (с демонстрацией)Эти две статьи могут лучше начать эту статью.

Хотя эта статья представляет собой продление предыдущей статьи, эта статья подробно представит конфигурацию каждого шага.


2. Создайте структуру проекта

Создайте новую папку и назовите ее:react-mobx-starter

mkdir react-mobx-starter 

инициализацияpackage.jsonдокумент

cd react-mobx-starter

# 直接生成默认的 package.json 文件
npm init -y

СоздайтеsrcКаталог, используемый для хранения кода, который мы написали Создайтеpublicкаталог для хранения публичных файлов Создайтеwebpackкаталог для храненияwebpackконфигурационный файл

mkdir src

mkdir public

mkdir webpack

в каталоге src Создайте новую папку страниц для хранения письменных компонентов страницы. Создайте новую папку компонентов для хранения общедоступных компонентов. Создайте новую папку utils для хранения часто используемых инструментов.

cd src

mkdir pages

mkdir components

mkdir utils

существуетpublicновый каталогindex.htmlдокумент существуетsrcновый каталогindex.jsдокумент существуетwebpackСоздано в каталогеwebpack.config.dev.jsа такжеwebpack.config.prod.js

  • webpack.config.dev.jsИспользуется для записи конфигурации среды разработки webpack.
  • webpack.config.prod.jsИспользуется для записи конфигурации производственной среды webpack.

index.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>React + Mobx 全家桶脚手架</title>
</head>
<body>
    <div id="root"></div>
</body>
</html>

index.js

function createElement() {
    const ele = document.createElement('div');
    ele.innerHTML = 'Hello, React';
    const root = document.querySelector('#root');
    root.appendChild(ele);
}

createElement();

webpack.config.dev.jsа такжеwebpack.config.prod.jsНа данный момент нет записи, мы поговорим об этом подробно позже.

Давайте сейчас посмотрим на структуру проекта, а затем настроим webpack.

react-mobx-starter
  ├─ public/
    └─ index.html
  ├─ src/
    ├─ components/
    ├─ pages/
    ├─ utils/
    └─ index.js
  ├─ webpack/
    ├─ webpack.config.dev.js
    └─webpack.config.prod.js
  ├─ package.json

3. Конфигурация среды разработки React

Добавьте скрипт выполнения в файл package.json для выполнения команды webpack:

{
    ...,
    "scripts": {
        "start": "webpack --config webpack/webpack.config.dev.js"
    },
    ...
}

Установите плагины, связанные с веб-пакетом

Установите веб-пакет и веб-пакет-кли

npm install webpack webpack-cli --save-dev

вход и выход

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

webpack.config.dev.js

const path = require('path');

const appSrc = path.resolve(__dirname, '../src');
const appDist = path.resolve(__dirname, '../dist');
const appPublic = path.resolve(__dirname, '../public');
const appIndex = path.resolve(appSrc, 'index.js');

module.exports = {
    entry: appIndex,
    output: {
        filename: 'public/js/[name].[hash:8].js',
        path: appDist,
        publicPath: '/'
    }
}

Добавить плагин html-webpack-plugin

Выполните скрипт запуска npm, вы можете увидетьdist/public/jsеще один в каталогеjsфайл, но этот созданhashСлишком хлопотно каждый раз вручную вносить его в файл index.html, чтобы его можно было импортироватьhtml-webpack-pluginплагин.

Плагин html-webpack-plugin имеет две функции.

  • могуpublicКопия папки в директории наdistв выходной папке
  • может автоматическиdistвнизjsфайл, импортированный вhtmlв файле

Установитьhtml-webpack-pluginплагин

npm install html-webpack-plugin --save-dev

использоватьhtml-webpack-pluginплагин

webpack.config.dev.js


const path = require('path');
+ const HTMLWebpackPlugin = require('html-webpack-plugin');

const appSrc = path.resolve(__dirname, '../src');
const appDist = path.resolve(__dirname, '../dist');
const appPublic = path.resolve(__dirname, '../public');
const appIndex = path.resolve(appSrc, 'index.js');
+ const appHtml = path.resolve(appPublic, 'index.html');

module.exports = {
    entry: appIndex,
    output: {
        filename: 'public/js/[name].[hash:8].js',
        path: appDist,
        publicPath: '/'
    },
+    plugins: [
+        new HTMLWebpackPlugin({
+            template: appHtml,
+            filename: 'index.html'
+        })
+    ]
}

Установить режим разработки

Атрибут режима в конфигурации веб-пакета может быть установлен на «разработка» и «производство», в настоящее время мы настраиваем среду разработки, поэтому его можно установить на «разработка».

webpack.config.dev.js

...
module.exports = {
+    mode: 'development',
    ...
}

установить инструмент разработки

Чтобы быстро найти неправильное местоположение, когда проект пойдет не так, вы можете настроить devtool для создания сопоставления ресурсов, мы используем здесьinline-source-mapБольше вариантов может бытьздесьУвидеть разницу.

webpack.config.dev.js

...
module.exports = {
    mode: 'development',
+    devtool: 'inline-source-map',
    ...
}

Запустите службу проекта с помощью webpack-dev-server.

Установить webpack-dev-сервер

npm install webpack-dev-server --save-dev

Настроить webpack-dev-сервер

webpack.config.dev.js

...
module.exports = {
    mode: 'development',
    devtool: 'inline-source-map',
+    devServer: {
+        contentBase: appPublic,
+        hot: true,
+        host: 'localhost',
+        port: 8000,
+        historyApiFallback: true,
+        // 是否将错误展示在浏览器蒙层
+        overlay: true,
+        inline: true,
+        // 打印信息
+        stats: 'errors-only',
+        // 设置代理
+        proxy: {
+            '/api': {
+                changeOrigin: true,
+                target: 'https://easy-mock.com/mock/5c2dc9665cfaa5209116fa40/example',
+                pathRewrite: {
+                    '^/api/': '/'
+                }
+            }
+        }
+    },
    ...
}

немного отремонтироватьpackage.jsonв файлеstartсценарий:

{
    ...,
    "scripts": {
        "start": "webpack-dev-server --config webpack/webpack.config.dev.js"
    },
    ...
}

Используйте плагин friendly-errors-webpack-plugin

friendly-errors-webpack-pluginПлагины могут лучше отображать подсказки в командной строке.

Установитьfriendly-errors-webpack-plugin:

npm install friendly-errors-webpack-plugin --save-dev

использоватьfriendly-errors-webpack-plugin:

webpack.config.dev.js


const path = require('path');
const HTMLWebpackPlugin = require('html-webpack-plugin');
+ const FriendlyErrorsWebpackPlugin = require('friendly-errors-webpack-plugin');

...

module.exports = {
    ...
    plugins: [
        new HTMLWebpackPlugin({
            template: appHtml,
            filename: 'index.html'
        }),
+        new FriendlyErrorsWebpackPlugin(),
    ]
}

включить горячую перезагрузку

webpack.config.dev.js

const path = require('path');
const HTMLWebpackPlugin = require('html-webpack-plugin');
const FriendlyErrorsWebpackPlugin = require('friendly-errors-webpack-plugin');
+ const webpack = require('webpack');

...

module.exports = {
    ...
    plugins: [
        ...
        new FriendlyErrorsWebpackPlugin(),
+        new webpack.HotModuleReplacementPlugin()
    ]
}

Запустите проект и протестируйте результаты конфигурации

воплощать в жизньnpm run startкоманда, после успешного выполнения командной строки откройте ее в браузереhttp://localhost:8000, можно увидетьHello React, что указывает на то, что базовая конфигурация Webpack выполнена успешно.

настроить бабел

прямо сейчас мыindex.jsОбъем кода внутри относительно небольшой, так что проблем нет. Но если я хочу использовать какой-то синтаксис ES6 или функции JS, которые не определены стандартом, нам нужно использовать babel для их преобразования. Давайте настроим егоbabel.

Установите плагин, связанный с Babel

npm install @babel/core babel-loader --save-dev

Использование babel-загрузчика

Задайте свойство cacheDirectory, указанный каталог будет использоваться для кэширования результата выполнения загрузчика. Последующие сборки веб-пакетов будут пытаться читать кеш, чтобы избежать потенциально дорогостоящего процесса перекомпиляции Babel при каждом выполнении.

webpack.config.dev.js

...
module.exports = {
    ...
    plugins: [ ... ],
    module: {
        rules: [
            {
                test: /\.(js|jsx)$/,
                loader: 'babel-loader?cacheDirectory',
                include: [ appSrc ],
                exclude: /node_modules/
            }
        ]
    }
}

Создайте новый файл babel.config.js в корневом каталоге проекта.

babel.config.jsФайл представляет собой управляющий файл времени выполнения, который автоматически считывается при компиляции проекта.babel.config.jsв файлеbabelконфигурация.

Используйте пресеты, связанные с babel

Установите соответствующие плагины:

  • @babel/preset-env: можно использовать все в проектеECMAScriptПоследние функции в стандарте.
  • @babel/preset-react: Может использоваться в проектеreactграмматика.
npm install babel-preset-env babel-preset-react --save-dev

настроитьbabel.config.jsдокумент:

module.exports = (api) => {
    api.cache(true);

    return {
        presets: [
            "@babel/preset-env",
            "@babel/preset-react"
        ]
    }
}

Используйте плагины, связанные с babel

babelобновитесь до7.0.0После версии,@babel/preset-stage-0Устаревшие, используемые плагины необходимо устанавливать самостоятельно. Если вы обновляетесь с более ранней версии до7.0.0версии официальный предоставляет новую команду, которая может напрямую помочь нам обновить проект:

npx babel-upgrade --write --install

больше оbabel-upgradeВведение может относиться кОфициальное описание.

Установите соответствующие плагины:

  • @babel/plugin-proposal-decorators: синтаксис декоратора можно использовать в проектах.
  • @babel/plugin-proposal-class-properties: Вы можете использовать новый синтаксис свойств класса в вашем проекте.
  • @babel/plugin-transform-runtimejsфайлы конвертируются, чтобы избежать избыточности кода.
  • @babel/runtime-corejs2:Сотрудничатьbabel-plugin-transform-runtimeПлагины используются парами
  • @babel/plugin-syntax-dynamic-import: можно использовать в проектеimport()этот синтаксис
  • @babel/plugin-proposal-export-namespace-from: Модули можно экспортировать с помощью экспорта пространства имен *
  • @babel/plugin-proposal-throw-expressions: вы можете использовать выражение для создания исключений.
  • @babel/plugin-proposal-logical-assignment-operators: вы можете использовать логический оператор присваивания
  • @babel/plugin-proposal-optional-chaining: Вы можете использовать дополнительную цепочку для доступа к глубоко вложенным свойствам или функциям?.
  • @babel/plugin-proposal-pipeline-operator: вы можете использовать оператор конвейера |>
  • @babel/plugin-proposal-nullish-coalescing-operator: Можно ли использовать синтаксис объединения null ??
  • @babel/plugin-proposal-do-expressions: можно использовать выражение do (подумайте о сложной версии тернарного оператора)
  • @babel/plugin-proposal-function-bind: вы можете использовать синтаксис связывания функций obj::func
npm install @babel/plugin-proposal-decorators @babel/plugin-proposal-class-properties @babel/plugin-transform-runtime @babel/runtime-corejs2 @babel/plugin-syntax-dynamic-import @babel/plugin-proposal-export-namespace-from @babel/plugin-proposal-throw-expressions @babel/plugin-proposal-logical-assignment-operators @babel/plugin-proposal-optional-chaining @babel/plugin-proposal-pipeline-operator @babel/plugin-proposal-nullish-coalescing-operator @babel/plugin-proposal-do-expressions @babel/plugin-proposal-function-bind --save-dev

настроитьbabel.config.jsдокумент:

module.exports = (api) => {
    api.cache(true);

    return {
        presets: [
            "@babel/preset-env",
            "@babel/preset-react"
        ],
        plugins: [
            [
                "@babel/plugin-proposal-decorators",
                {
                    "legacy": true
                }
            ],
            [
                "@babel/plugin-transform-runtime",
                {
                    "corejs": 2
                }
            ],
            [
                "@babel/plugin-proposal-class-properties", 
                { 
                    "loose": true
                }
            ],
            "@babel/plugin-syntax-dynamic-import",
            // 可以使用 export * 这种命名空间的方式导出模块
            "@babel/plugin-proposal-export-namespace-from",
            // 可以使用异常抛出表达式,
            "@babel/plugin-proposal-throw-expressions",
            // 默认导出
            "@babel/plugin-proposal-export-default-from",
            // 可以使用逻辑赋值运算符
            "@babel/plugin-proposal-logical-assignment-operators",
            // 可以使用可选链的方式访问深层嵌套的属性或者函数 ?.
            "@babel/plugin-proposal-optional-chaining",
            // 可以使用管道运算符 |> 
            [
                "@babel/plugin-proposal-pipeline-operator",
                {
                    "proposal": "minimal"
                }
            ],
            // 可以使用空值合并语法 ??
            "@babel/plugin-proposal-nullish-coalescing-operator",
            // 可以使用 do 表达式(可以认为是三元运算符的复杂版本)
            "@babel/plugin-proposal-do-expressions",
            // 可以使用功能绑定语法 obj::func
            "@babel/plugin-proposal-function-bind"
        ]
    }
}

Обратите внимание здесь@babel/plugin-proposal-decoratorsПорядок размещения плагинов должен быть первым, иначе некоторые аннотации могут не работать.

На этом базовая конфигурация, связанная с babel, завершена. После этого мы можем свободно использовать всевозможные новые возможности JS в проекте.

Добавить загрузчик, связанный с css

jsДокументы, связанныеbabel-loaderНастроено, но иногда хочется добавить какие-то стили к элементам в проекте, иwebpackдумаю, что все это модуль, поэтому нам нужно что-то еще в это времяloaderДавайте разберем волну кода стиля.

Установите соответствующие плагины:

  • css-loader:иметь дело сcssв файлеurl()Ждать.
  • style-loader:Будуcssвставил на страницуstyleЭтикетка.
  • less-loader: да будетlessфайл, скомпилированный вcss.
  • postcss-loader: Многие плагины могут быть интегрированы для работыcss. Мы используем его здесь для интеграцииautoprefixerдля автоматического добавления префикса.
npm install css-loader style-loader less less-loader postcss-loader autoprefixer --save-dev

Настройка загрузчиков, связанных со стилем

  • из-заReactНевозможно напрямую использовать что-то вродеVueсерединаscopeЭто локальные переменные эффекта, поэтому мы можем использоватьwebpackкоторый предоставилCSS Module. 2. Потому что он будет использоваться позжеantd, так представьтеantdнужно включитьlessизjavascriptВариант, так чтоless-loaderсвойства вjavascriptEnabledУстановить какtrue.

Настройте в webpack.config.dev.js:

...
const autoprefixer = require('autoprefixer');

module.exports = {
    ...,
    plugins: [...],
    module: {
        rules: [
            ...,
            {
                test: /\.(css|less)$/,
                exclude: /node_modules/,
                use: [{
                        loader: 'style-loader'
                    },
                    {
                        loader: 'css-loader',
                        options: {
                            sourceMap: true,
                            modules: true,
                            localIdentName: '[local].[hash:8]'
                        }
                    },
                    {
                        loader: 'postcss-loader',
                        options: {
                            plugins: () => [autoprefixer()]
                        }
                    },
                    {
                        loader: 'less-loader',
                        options: {
                            javascriptEnabled: true
                        }
                    }
                ]
            },
            {
                test: /\.(css|less)$/,
                include: /node_modules/,
                use: [{
                        loader: 'style-loader'
                    },
                    {
                        loader: 'css-loader',
                        options: {}
                    },
                    {
                        loader: 'postcss-loader',
                        options: {
                            plugins: () => [autoprefixer()]
                        }
                    },
                    {
                        loader: 'less-loader',
                        options: {
                            javascriptEnabled: true
                        }
                    }
                ]
            },
        ]
    }
}

Добавьте дополнительные модули для решения конфигурации загрузчика

Установите соответствующие плагины:

npm install file-loader csv-loader xml-loader html-loader markdown-loader --save-dev

Настройте в webpack.config.dev.js:

...

module.exports = {
    ...,
    plugins: [...],
    module: {
        rules: [
            ...,
            // 解析图片资源
            {
                test: /\.(png|svg|jpg|gif)$/,
                use: [
                    'file-loader'
                ]
            },
            // 解析 字体
            {
                test: /\.(woff|woff2|eot|ttf|otf)$/,
                use: [
                    'file-loader'
                ]
            },
            // 解析数据资源
            {
                test: /\.(csv|tsv)$/,
                use: [
                    'csv-loader'
                ]
            },
            // 解析数据资源
            {
                test: /\.xml$/,
                use: [
                    'xml-loader'
                ]
            },
            // 解析 MakeDown 文件
            {
                test: /\.md$/,
                use: [
                    'html-loader',
                    'markdown-loader'
                ]
            }
        ]
    }
}

Дополнительные оптимизации конфигурации веб-пакета

Добавить свойство разрешения псевдонима, установить псевдоним

В процессе разработки проекта, по мере того, как проект становится больше и уровень файлов становится все глубже и глубже, может возникнуть необходимость найти путь послойно при импорте файлов, что будет громоздко.resolveсерединаaliasСвойства задают псевдонимы для некоторых часто используемых папок

webpack.config.dev.js

··· 

module.exports = {
    ...,
    plugins: [...],
    module: {...},
+    resolve: {
+        alias: {
+            src: appSrc,
+            utils: path.resolve(__dirname, '../src/utils'),
+            pages: path.resolve(__dirname, '../src/pages'),
+            components: path.resolve(__dirname, '../src/components')
+        }
+    }
}

Добавьте свойство resolve.modules, чтобы указать, где хранятся сторонние модули.

Мы знаем, что когда модуль обычно ищется, он начинается с текущего каталога.node_modulesПоиск до корневого каталога дискаnode_modules. Итак, чтобы уменьшить шаги поиска, мы можем установитьresolve.modulesАтрибуты принудительно применяются только из элементаnode_modulesНайдите модули в .

webpack.config.dev.js

··· 

module.exports = {
    ...,
    plugins: [...],
    module: {...},
    resolve: {
        ...,
+        modules: [path.resolve(__dirname, '../node_modules')],
    }
}

Установите плагины, связанные с React, MObx и React Router.

npm install react react-dom prop-types mobx mobx-react react-router-dom --save

импортировать и

согласно сantdОписание официальный сайт, напрямуюbabel.config.jsДобавьте конфигурацию в файл, а затем вы можете использовать его нормально в проекте.

Установите и связанные с ним плагины:

npm install antd moment --save

Установите babel-plugin-import для загрузки компонентов по запросу:

npm install babel-plugin-import --save-dev

существуетbabel.config.jsДобавьте конфигурацию antd в файл:

module.exports = (api) => {
    api.cache(true);
    
    return {
        presets: [
            ...
        ],
        plugins: [
            ...,
    +        [
    +            "import",
    +            {
    +                "libraryName": "antd",
    +                "style": true
    +            }
    +        ],
            ...
        ]
    }

В-четвертых, вести React-разработку

В основном необходимые плагины введены, пора развиваться.

Измените файл index.js в корневом каталоге.

index.js

import React from 'react';
import ReactDom from 'react-dom';
import { Provider } from 'mobx-react'
import { LocaleProvider } from 'antd';
import { HashRouter } from 'react-router-dom';
import zh_CN from 'antd/lib/locale-provider/zh_CN';
import 'moment/locale/zh-cn';

import GlobalModel from './GlobalModel';
// import App from './App';

const globalModel = new GlobalModel();

const App = () => {
    return <div>开发环境配置完成</div>
}

ReactDom.render(
    <Provider globalModel={ globalModel }>
        <LocaleProvider locale={zh_CN}>
            <HashRouter>
                <App />
            </HashRouter>
        </LocaleProvider>
    </Provider>,
    document.querySelector('#root')
);

бегатьnpm run startкоманда, открыть в браузереhttp://localhost:8000/, ты можешь видетьНастройка среды разработки завершенанормальный дисплей.

На данный момент это означает, что наши различные плагины и библиотеки были представлены и могут использоваться в обычном режиме.

ИСПОЛЬЗОВАНИЕ РАСПОЛОЖЕННОГО РАСПОЛОЖЕНИЯ ПЕРВЫЙ ПЕРВЫ

Создайте новый файл App.js в каталоге src:

App.js

import React from 'react';
import { Switch, Route } from 'react-router-dom';

import Home from 'pages/home';
import Settings from 'pages/settings';
import Display from 'pages/display';
import NotFound from 'pages/exception'

import styles from './App.less';


export default (props) => {
    return (
        <div className={ styles.app }>
            <Switch>
                <Route path='/settings' component={ Settings } />
                <Route path='/display' component={ Display } />
                <Route exact path='/' component={ Home } />
                <Route component={ NotFound } />
            </Switch>
        </div>
    )
}

существуетsrcСоздано в каталогеApp.lessфайл, пишиAppстиль компонента

App.less

.app {
    padding: 60px;
}

Записать компоненты Home, Settings, Display, NotFound в каталог pages

  • HomeКомпонент является компонентом корневой маршрутизации, используемый для перехода кSettingинтерфейс иDisplayинтерфейс
  • SettingsКомпоненты демонстрируют, как получить и изменитьmobxглобальныйModel
  • DisplayКомпонент демонстрирует, как использовать mobx для синхронной и асинхронной обработки данных.
  • NotFoundКомпонент отображается, когда он не соответствует правильному маршруту

Home、Settings、Display 相关的代码我就不贴了,占的篇幅较长,大家需要的话可以去我的 Github 上看一下或者下载下来也可以。 Более удобный. адрес:Github

Снова измените файл index.js.

index.js

import React from 'react';
import ReactDom from 'react-dom';
import { Provider } from 'mobx-react'
import { LocaleProvider } from 'antd';
import { HashRouter } from 'react-router-dom';
import zh_CN from 'antd/lib/locale-provider/zh_CN';
import 'moment/locale/zh-cn';

import GlobalModel from './GlobalModel';
import App from './App';

const globalModel = new GlobalModel();

ReactDom.render(
    <Provider globalModel={ globalModel }>
        <LocaleProvider locale={zh_CN}>
            <HashRouter>
                <App />
            </HashRouter>
        </LocaleProvider>
    </Provider>,
    document.querySelector('#root')
);

Вы можете видеть, что естьGlobalModelЛогика в модели, которая хранит глобальные общие данные, относительно проста, давайте посмотрим.

GlobalModel.js

import { observable, action } from 'mobx';

export default class GlobalModel {
    @observable username = '小明';

    @action
    changeUserName = (name) => {
        this.username = name;
    }

}

Добавьте класс инструмента выборки для сетевых запросов.

Поскольку нам нужно выполнять асинхронные операции сетевых запросов в компоненте Display, мы вводим здесь fetch для выполнения сетевых запросов.

Установите плагины, связанные с выборкой:

npm install whatwg-fetch qs --save

Напишите класс инструмента сетевого запроса

существуетutilsСоздано в каталогеrequest.jsдокумент.

utils/request.js

import 'whatwg-fetch';
import { stringify } from 'qs';

/**
 * 使用 Get 方式进行网络请求
 * @param {*} url 
 * @param {*} data 
 */
export const get = (url, data) => {
    const newUrl = url + '?' + stringify(data) + (stringify(data) === '' ? '' : '&') +'_random=' + Date.now();
    return fetch(newUrl, {
            cache: 'no-cache',
            headers: {
                'Accept': 'application/json',
                'Content-Type': 'application/json; charset=utf-8'
            },
            method: 'GET',
        })
        .then(response => response.json());
}

/**
 * 进行 Post 方式进行网络请求
 * @param {*} url 
 * @param {*} data 
 */
export const post = (url, data) => {
    return fetch(url, {
        body: JSON.stringify(data), 
        cache: 'no-cache',
        headers: {
            'Accept': 'application/json',
            'Content-Type': 'application/json; charset=utf-8'
        },
        method: 'POST',
    })
    .then(response => response.json()) // parses response to JSON
}

На данный момент построен простой фреймворк React.

воплощать в жизньnpm run start, после успешной компиляции видно, что интерфейс выглядит вот так.

Домашний интерфейс:

Home 界面

Интерфейс настроек:

Settings 界面

Интерфейс дисплея:

Display 界面

Интерфейс не найден:

NotFound 界面


В-пятых, выполните настройку упаковки проекта React.

Сначала добавьте скрипт выполнения в файл package.json:

{
    ...,
    "scripts": {
        "start": "webpack-dev-server --config webpack/webpack.config.dev.js",
        "build": "webpack --config webpack/webpack.config.prod.js"
    },
    ...
}

Файл конфигурации Webpack.config.prod.js

Большинство изmoduleа такжеpluginа такжеresolve都与开发环境的一致。 Так что мы должныwebpack.config.dev.js

  • Измените значение свойства режима на: «производство».
  • Измените значение свойства devtool на: 'hidden-source-map'
  • Удалите всю конфигурацию из свойства devServer.
  • Удалить используемые плагины тепловой нагрузки: · WebPack.hotmoduleReplationPlugin`,

Добавить атрибуты оптимизации кода сжатия

Установите соответствующие плагины:

npm install uglifyjs-webpack-plugin optimize-css-assets-webpack-plugin --save-dev

Добавьте конфигурацию сжатия кода:

webpack.config.prod.js

...;
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
...;

module.exports = {
    mode: 'production',
    devtool: 'hidden-source-map',
    entry: ...,
    output: {...},
    plugins: [...],
    module: {...},
    optimization: {
        // 打包压缩js/css文件
        minimizer: [
            new UglifyJsPlugin({
                uglifyOptions: {
                    compress: {
                        // 在UglifyJs删除没有用到的代码时不输出警告
                        warnings: false,
                        // 删除所有的 `console` 语句,可以兼容ie浏览器
                        drop_console: true,
                        // 内嵌定义了但是只用到一次的变量
                        collapse_vars: true,
                        // 提取出出现多次但是没有定义成变量去引用的静态值
                        reduce_vars: true,
                    },
                    output: {
                        // 最紧凑的输出
                        beautify: false,
                        // 删除所有的注释
                        comments: false,
                    }
                }
            }),
            new OptimizeCSSAssetsPlugin({})
        ],
        splitChunks: {
            cacheGroups: {
                styles: {
                    name: 'styles',
                    test: /\.(css|less)/,
                    chunks: 'all',
                    enforce: true,
                    reuseExistingChunk: true // 表示是否使用已有的 chunk,如果为 true 则表示如果当前的 chunk 包含的模块已经被抽取出去了,那么将不会重新生成新的。
                },
                commons: {
                    name: 'commons',
                    chunks: 'initial',
                    minChunks: 2,
                    reuseExistingChunk: true
                },
                vendors: {
                    name: 'vendors',
                    test: /[\\/]node_modules[\\/]/,
                    priority: -10,
                    reuseExistingChunk: true
                }
            }
        },
        runtimeChunk: true
    },
    resolve: {...}
}

Извлеките код CSS с помощью плагина mini-css-extract-plugin.

Установите соответствующие плагины:

npm install mini-css-extract-plugin --save-dev

настроитьmini-css-extract-pluginПлагин:

  • существуетpluginsВведение в атрибуты
  • БудуmoduleизrulesИспользовалstyle-loaderзаменитьMiniCssExtractPlugin.loader

webpack.config.prod.js

...
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
    ...,
    plugins: [
        ...,
        new MiniCssExtractPlugin({
            filename: 'public/styles/[name].[contenthash:8].css',
            chunkFilename: 'public/styles/[name].[contenthash:8].chunk.css'
        })
    ],
    modules: {
        rules: [
            ...,
            {
                test: /\.(css|less)$/,
                exclude: /node_modules/,
                use: [
                    {
-                        loader: 'style-loader'
+                        loader: MiniCssExtractPlugin.loader
                    },
                    ...
                ]
            },
            {
                test: /\.(css|less)$/,
                exclude: /node_modules/,
                use: [
                    {
-                        loader: 'style-loader'
+                        loader: MiniCssExtractPlugin.loader
                    },
                    ...
                ]
            },
            ...
        ]
    },
    ...
}

webpack.config.prod.js

...
module.exports = {
    ...,

    plugins: [
        ...,
        new webpack.DefinePlugin({
            // 定义 NODE_ENV 环境变量为 production
            'process.env': {
                NODE_ENV: JSON.stringify('production')
            }
        })
    ],
    ...
}

Поскольку в процессе упаковки некоторые имена файлов используют хэш-значения, файлы каждый раз будут разными, поэтому в dist. Таким образом, мы можем очищать каталог dist перед каждым пакетом.

Установите плагин:

npm install clean-webpack-plugin --save-dev

Используйте плагин:

webpack.config.prod.js

...,

module.exports = {
    ...,
    plugins: [
        ...,
        new CleanWebpackPlugin()
    ],
    ...
}

Добавьте другие конфигурации оптимизации

  • Добавлена ​​настройка статистики для фильтрации некоторых статистических данных, которые появляются при упаковке.
  • Добавьте конфигурацию производительности, чтобы отключить подсказки по производительности.

webpack.config.prod.js

module.exports = {
    ...,
    stats: {
        modules: false,
        children: false,
        chunks: false,
        chunkModules: false
    },
    performance: {
        hints: false
    }
}

Упаковать и выпустить проект

Упаковать проект

бегатьnpm run buildДиректива, после того, как пакеты консоли будут завершены, корневой каталог будет больше.distпапка.

Опубликовать проект с помощью Nginx

я использую здесьNginxКак сервер, опубликован локально.

Nginxссылка на скачивание:.

下载完成之后,解压完成。 ОткрытьNginxconfпапка, найтиnginx.confфайл, конфигурация в модификаторе:

Nginx 配置

отмечено на рисункеhtmlзаменитьdist.

Затем мы можем безопасно упаковать сгенерированныйdistпапку прямо вNginxв каталоге установки. (В настоящее времяdistкаталог с предыдущимconfкаталоги должны быть на одном уровне).

запускатьNginxСлужить:

start nginx

Откройте браузер и введитеhttp://127.0.0.1илиhttp://localhostВы можете видеть, что наш проект работает нормально.

Другие команды Nginx:

# 停止 Nginx 服务
nginx -s stop

# 重启 Nginx 服务
nginx -s reload

# 退出 nginx
nginx -s quit

Для получения дополнительной информации, связанной с Ngnix, обратитесь к:Официальная документация Nginx

Примечание. Команды, связанные с nginx, необходимо выполнять в каталоге установки Nginx!


6. Используйте WebPack-Merge, чтобы ввести общедоступную конфигурацию WebPack.

Наблюдаемыйwebpack.config.dev.jsа такжеwebpack.config.prod.jsможно обнаружить, что в нем много дублирования кода и конфигурации. Таким образом, мы можем написатьwebpack.common.jsфайл, поместите в него общую конфигурацию и используйтеwebpack-mergewebpack.config.dev.jsа такжеwebpack.config.prod.js

npm install webpack-merge --save-dev

использовать:

+ const merge = require('webpack-merge');
+ const common = require('./webpack.common.js');

+ module.exports = merge(common, {
+   mode: 'production',
+   ...
+ });

这里就展示了一下用法,由于篇幅太长,三个文件中具体的配置代码我就不贴了, Ты можешь пойти вмой GitHubПроверьте это с помощьюwebpack-mergeПосле файла конфигурации.


Семь, Адрес источника бумаги

react-mobx-starter

Добро пожаловать Звезда, спасибо!

Если есть какие-либо проблемы в статье и коде, пожалуйста, поправьте меня, спасибо!


официальный сайт вебпака

Создание конфигурации среды разработки Webpack с нуля (с демонстрацией)

Используйте Webpack для настройки производственной среды (с демонстрацией)