Как наилучшим образом оптимизировать начальную загрузку страницы для реакции веб-приложения с изображениями, особенно для мобильных устройств?

У меня есть довольно сложное веб-приложение, написанное на React/Redux и веб-пакет для компиляции. Его целевая страница состоит из 2 изображений и основного модуля приложения. Все остальные модули загружаются в зависимости от того, что хочет сделать пользователь. Когда я проверяю с помощью Google Devtools, я получаю 74 балла производительности, что неплохо.

Но начальная страница загружается через 15 секунд на iPhone! И мне нужно оптимизировать это.

Изображения Одним из изображений является фон html тела, которое показывает, когда загружаются другие страницы. Другой - фон компонента домашней страницы. Изображение домашней страницы не подлежит обсуждению, оно должно быть там. Тот, в теле я более гибок, но выглядит круто.

Прямо сейчас изображение домашней страницы импортируется в компонент реагирования с помощью url-загрузчика веб-пакета и поэтому находится в комплекте приложения. Это лучший способ? Другое изображение загружается в index.html непосредственно в элементе body. Я не уверен, что это самый быстрый способ.

Я не эксперт по изображениям, так что, может быть, я могу еще что-нибудь сделать, чтобы сжать или оптимизировать изображения? Существует ли "лучший размер" для использования кроссплатформенного? Также какие инструменты использовать, чтобы изменить? У меня есть GIMP в моей системе, но я могу использовать что-то еще.

Всплеск Было бы неплохо, если бы пользователь сразу увидел "что-то" во время загрузки, чтобы он мог быть более терпеливым. Прямо сейчас они видят только пустой белый экран. Я следую за всеми генераторами favicon, и у меня все они настроены в соответствии с указаниями. Но всплеск не показывает. Есть ли что-то, что я могу сделать там? Я даже пытался изменить прямо в HTML другой цвет фона, но он также не обнаруживается.

CSS Чтобы организовать код моего проекта, я построил все очень компонентно. Мои таблицы стилей в основном располагаются рядом с каждым компонентом и импортируются туда, где он используется. Они также упаковываются через веб-пакет с использованием miniCssExtractLoader и css-loader. Я прилагаю свои конфиги вебпака - могу ли я там что-нибудь сделать?

Webpack Что еще я могу сделать, чтобы уменьшить начальное время загрузки? Вот мои настройки webpack.common и webpack.prod. Любые идеи будут оценены!

webpack.common.js

const path = require('path');
var webpack = require('webpack');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const sourcePath = path.join(__dirname, './src');
const autoprefixer = require('autoprefixer');
const CopyWebpackPlugin = require('copy-webpack-plugin');


module.exports = {
  entry: {
      app: './src/index.js'
  },
  output: {
      filename: '[name].[chunkhash:4].js',
      chunkFilename: '[name].[chunkhash:4].js', //name of non-entry chunk files
      path: path.resolve(__dirname, 'dist'),  //where to put the bundles
      publicPath: "/" // This is used to generate URLs to e.g. images
    },
  module: {
      rules: [
        {
          test: /\.(js|jsx)$/,
          exclude: /node_modules/,
          use: {
            loader: "babel-loader"
          }
        },
        {
          test: /\.html$/,
          use: [
            {
              loader: "html-loader",
              options: { minimize: true }
            }
          ]
        },

        {
          test: /\.(scss|sass|css)$/,
          use: [
              MiniCssExtractPlugin.loader,
              { loader: 'css-loader' },
              { loader: 'postcss-loader',
                  options: {
                    plugins: () => [autoprefixer({ grid: false})]
                  }
              },
              {
                loader: 'fast-sass-loader',
                options: {
                  includePaths: [  path.resolve(__dirname, 'src'), path.resolve(__dirname, 'src','styles') ,'./node_modules', '/node_modules/materialize-css/sass/components'],
                  sourceMap: true
                }
              }
          ]

        },
        {
          test: /\.(jpg|png)$/,
          loader: 'url-loader',
          options: {
            limit: 8192 // inline base64 URLs for <=8k images, direct URLs for the rest
          },
        },
        {    
          test: /\.svg/,
          use: {
            loader: 'svg-url-loader',
            options: {}
          }
        }

      ]
    },

    resolve: {
      alias: {
        components:  path.resolve(__dirname, 'src', 'components'),
        navigation:  path.resolve(__dirname, 'src', 'navigation'),
        reducers:    path.resolve(__dirname, 'src', 'reducers'),
        actions:     path.resolve(__dirname, 'src', 'actions'),
        routes:      path.resolve(__dirname, 'src', 'routes'),
        utils:       path.resolve(__dirname, 'src', 'utils'),
        styles:      path.resolve(__dirname, 'src', 'styles'),
        images:      path.resolve(__dirname, 'public', 'images'),
        public:      path.resolve(__dirname, 'public'),
        test:        path.resolve(__dirname, 'src', 'test'),
        materialize: path.resolve(__dirname, 'node_modules', 'materialize-css', 'sass', 'components')
      },
      // extensions: ['.webpack-loader.js', '.web-loader.js', '.loader.js', '.js', '.jsx'],
      modules: [
        path.resolve(__dirname, 'node_modules'),
        sourcePath
      ]
    },
    optimization: {
          splitChunks: {
              cacheGroups: {
                  js: {
                      test: /\.js$/,
                      name: "commons",
                      chunks: "all",
                      minChunks: 7,
                  },
                  styles: {
                    test: /\.(scss|sass|css)$/,
                    name: "styles",
                    chunks: "all",
                    enforce: true
                  }
              }
          }
    },
  plugins: [
    new CleanWebpackPlugin(['dist']),
    new CopyWebpackPlugin([ { from: __dirname + '/public', to: __dirname + '/dist/public' } ]),
    new MiniCssExtractPlugin({filename: "[name].css"}),
    new webpack.NamedModulesPlugin(),
    new HtmlWebpackPlugin({
       "template": "./src/template.html",
       "filename": "index.html",
       "hash": false,
       "inject": true,
       "compile": true,
       "favicon": false,
       "minify": true,
       "cache": true,
       "showErrors": true,
       "chunks": "all",
       "excludeChunks": [],
       "title": "ShareWalks",
       "xhtml": true,
       "chunksSortMode": 'none' //fixes bug
       })
   ]
};

webpack.prod.js

 const merge = require('webpack-merge');
 const common = require('./webpack.common.js');
const WorkboxPlugin = require('workbox-webpack-plugin');


 module.exports = merge(common, {
   mode: 'production',
   devtool: 'source-map',
   plugins: [
          new WorkboxPlugin.GenerateSW({ 
          // these options encourage the ServiceWorkers to get in there fast     
           // and not allow any straggling "old" SWs to hang around     
           clientsClaim: true,     
           skipWaiting: true
      }),
   ]
});

1 ответ

Ваш вопрос слишком широк для SO и будет закрыт:) Давайте сосредоточимся на том, как оптимизировать пакет.

Свободная компиляция Babel 1.try (меньше кода)

module.exports = {
  "presets": [
    ["@babel/preset-env", {
      // ...
      "loose": true
    }]
  ],
}

2. Также просмотрите ваши полифилы, используйте минификацию, изучите веб-пакет null-loader techique.

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

optimization: {
    runtimeChunk: 'single',
    splitChunks: {
      chunks: 'all',
      maxInitialRequests: infinity,
      cacheGroups: {
        vendor: {
          test: /[\\/]node_modules[\\/]/,
          vendorname(v) {
            var name = v.context.match(/[\\/]node_modules[\\/](.*?)([\\/]|$)/)[1];
            return `npm.${name.replace('@', '_')}`;
          },
        },
      },
Другие вопросы по тегам