1

我正在使用 HTML5、JavaScript 和 React 创建一个网站。我正在使用 Google Chrome Lighthouse 来检查网站首次加载的性能。

这是 Lighthouse 运行时环境:

  • 用户代理:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36
  • 设备仿真 Nexus 5X:已启用
  • 网络节流 562.5ms RTT, 1.4Mbps down, 0.7Mbps up: 启用
  • CPU Throttling 4x 减速:启用

经过多次迭代和修复,这些是我目前在 Lighthouse 上的得分:

  • 性能 57
  • 渐进式网络应用 100
  • 无障碍 100
  • 最佳实践 88
  • 搜索引擎优化 100

最佳实践不是 100,因为:

  • 我拥有的主机不提供 HTTP/2(如果这真的是一个问题,我可能会改变)
  • 我有带有 document.write() 的 Google Ads 脚本(对此无法更改)

我的大问题是性能指标。我有一个超过 3.3 秒的白色空白屏幕,并且在 8.3 秒后完全显示!第一次有意义的绘制为 5,750 毫秒,第一次交互为 6,720 毫秒(与一致交互相同)感知速度指数为 4,228(得分 64),估计输入延迟为 16 毫秒(得分 100)

这是关键链请求: 关键链请求

这是网络概述: 网络概览

这是我到目前为止所做/尝试过的:

  • 使用 react-code-splitting 将起始页面中的所有组件移动到异步加载
  • 优化图像以使用新的 J2P、JXR 和 WEBP 格式,并使它们的大小正确,因此浏览器不必调整它们的大小。
  • 将 App.js 的内容移动到 index.js 中(在加载之前会并行获取 index.js 和 vendor.js,然后是一个包含所有 css 文件和 app.js 的 js 文件,之后它将并行加载app.js 中使用的组件
  • 将一些 css 导入移动到与它们关联的组件中。
  • 使用 webpack-bundle-analyzer 尝试查找常用库以及它们是如何拆分的。正如您在以下屏幕截图中看到的那样,我的包中有很多重复的模块,我找不到如何提取以提高效率。(lodash,react-overlays,...)

捆绑

这是我的 webpack.config.js

const webpack = require('webpack');
const path = require('path');

const HtmlWebpackPlugin = require('html-webpack-plugin');
const ChunkManifestPlugin = require('chunk-manifest-webpack-plugin');
const WebpackChunkHash = require('webpack-chunk-hash');
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
//var SWPrecacheWebpackPlugin = require('sw-precache-webpack-plugin');
const OfflinePlugin = require('offline-plugin');

// To handle the regeneratorRuntime exception
require('babel-polyfill');

require('file-loader');
require('css-loader');
require('style-loader');
require('html-webpack-template');

/* Shared Dev & Production */

const config = {
  context: path.resolve(__dirname, 'src'),

  entry: {
    index: [
        // To handle the regeneratorRuntime exception
        'babel-polyfill',
        './index.js'
    ],
    vendor: ['offline-plugin/runtime', 'react', 'react-dom', 'react-router', 'react-redux', 'history', 'react-router-dom', 'redux', 'react-router-redux', 'redux-form', 'lodash'],
  },

  module: {
    rules: [
      {
        test: /\.js$/,
        use: 'babel-loader',
        exclude: /node_modules/,
      },
      {
        test: /\.(ico|jpg|png|gif|eot|otf|jp2|jxr|webp|svg|ttf|woff|woff2)(\?.*)?$/,
        exclude: /\/favicon.ico$/,
        use: [
          {
            loader: 'file-loader',
            query: {
              name: '[path][name][hash].[ext]',
              publicPath: '/'
            }
          }
        ]
      },
      {
        test: /\.css$/,
        include: path.join(__dirname, 'src/style'),
        use: [
          'style-loader',
          {
            loader: 'css-loader',
            options: {
              minimize: true
            }
          }
        ]
      },
      {
        test: /\.(ico)(\?.*)?$/,
        exclude: /node_modules/,
        use: {
          loader: 'file-loader',
          options: { name: '[name].[ext]' },
        },
      },
      {
        test: /\.xml/,
        use: {
          loader: 'file-loader',
          options: { name: '[name].[ext]' },
        },
      },
    ],
  },

  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].bundle.js',
    publicPath: '/',
  },

  resolve: {
    extensions: ['.js'],
    modules: [path.resolve(__dirname, 'src'), 'node_modules'],
  },

  plugins: [
    // New moment.js optimization
    new webpack.ContextReplacementPlugin(/moment[\/\\]locale$/, /en/),

    new webpack.optimize.CommonsChunkPlugin({
      name: 'vendor',
      minChunks: 2
    }),

    new webpack.optimize.ModuleConcatenationPlugin(),

    new HtmlWebpackPlugin({
      appMountId: 'app-root',
      inlineManifestWebpackName: 'webpackManifest',
      template: 'templateIndex.html',
      title: 'Our Site',
    }),

    new OfflinePlugin({
      AppCache: false,
      ServiceWorker: { events: true },
    }),

    new BundleAnalyzerPlugin({analyzerMode: 'static'}),
  ],

  devServer: {
    historyApiFallback: true,
  },
};

//if (process.env.NODE_ENV === 'production') {
config.output.filename = '[name].[chunkhash].js';
config.plugins = [
  ...config.plugins,
  new webpack.HashedModuleIdsPlugin(),
  new WebpackChunkHash(),
  /*new ChunkManifestPlugin({
    filename: 'chunk-manifest.json',
    manifestVariable: 'webpackManifest',
    inlineManifest: true,
  }),*/
];
//}

module.exports = config;

我的.babelrc

{
  "presets": [
    [
      "env",
      { "modules": false }
    ],
    "react",
    "stage-0",
    "stage-2"
  ],
  "plugins": [ "syntax-dynamic-import", "transform-react-jsx", "transform-decorators-legacy" ]
}

还有我的 index.js

import React from 'react';
import { render } from 'react-dom';
import { BrowserRouter } from "react-router-dom";
import {Redirect, Route, Switch, withRouter} from 'react-router';
import { Provider } from 'react-redux';
import Async from 'react-code-splitting';

const TopBar = () => (<Async load={import('./containers/TopBar/TopBarAsync')} />);
const NavBar = () => (<Async load={import('./containers/NavBar/NavBarAsync')} />);
const BottomBar = () => (<Async load={import('./containers/BottomBar/BottomBarAsync')} />);
const UserHelpers = (props) => <Async load={import('./containers/UserHelpers')} componentProps={props} />
const Main = () => (<Async load={import('./containers/Main')} />);
const Blog = () => (<Async load={import('./containers/Blog')} />);
const PublicPage = () => (<Async load={import('./containers/PublicPage')} />);

import configureStore from './store/store';
const store = configureStore();

import './styles/font-awesome.min.css';

import './styles/app.css';
import './styles/TeamBrowser.css';

let googleTracking = null;
if(process.env.NODE_ENV==='production') {
  // https://web-design-weekly.com/2016/07/08/adding-google-analytics-react-application/
  ReactGA.initialize([my key here]);
  googleTracking = function fireTracking() {
    let page=window.location.pathname+window.location.search;
    ReactGA.set({ page: page });
    ReactGA.pageview(page);
  }

  const runtime=require('offline-plugin/runtime');
  runtime.install({
    onUpdateReady() {
      runtime.applyUpdate();
    },
    onUpdated() {
      window.location.reload();
    },
  });
}

render((
  <Provider
    store={store}>
    <BrowserRouter
      onUpdate={googleTracking}>
      <div className="body">
        <header>
          <TopBar/>
          <NavBar />
        </header>
        <main>
          <Switch>
            <Route path="/" exact component={Main} />
            <Route path="/main" component={Main} />
            <Route path="/Feed" component={Blog} />
            <Route path="/Blog" component={Blog} />
            <Route path="/:id" component={PublicPage} />
           <Redirect to="/" />
          </Switch>
        </main>
        <footer
          className="footer">
          <BottomBar />
        </footer>
        <UserHelpers />
      </div>
    </BrowserRouter>
  </Provider>),
  document.getElementById('app'));

现在我不知道如何提高加载速度以获得更好的 Lighthouse 分数。任何人都可以发现我不知道的任何事情吗?

在我看来,chunk-manifest-webpack-plugin 似乎没有正常工作,因为它没有提取所有常见模块。其次,index.[hash].js 包包含它不应该包含的文件(例如:utils.js、“actions”文件夹下的文件……这些是我自己的文件,但在我的索引中没有引用它们.js 那么为什么要把它们放在那里呢?

4

0 回答 0