我正在构建一个React站点,我不确定我是否正确编译,因为第一次加载库需要大约5秒钟(之后它会被缓存,所以它更快)。 我需要帮助才能找到我做错的事情并减慢加载时间。
我在这里发布我正在使用的文件。
的package.json
{
"name": "MySite",
"version": "0.1.0",
"description": "Something",
"private": true,
"devDependencies": {
"babel-plugin-react-html-attrs": "^2.0.0",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-polyfill": "^6.23.0",
"babel-preset-stage-2": "^6.24.1",
"babili-webpack-plugin": "^0.1.2",
"compression-webpack-plugin": "^1.0.0",
"react-hot-loader": "^1.3.1",
"react-scripts": "1.0.10",
"serve-favicon": "^2.4.3",
"webpack-dev-server": "^2.5.1",
"webpack-hot-middleware": "^2.18.2"
},
"dependencies": {
"ajv": "^5.2.2",
"axios": "^0.16.2",
"babel-core": "^6.25.0",
"babel-loader": "^7.1.1",
"babel-plugin-transform-class-properties": "^6.24.1",
"babel-plugin-transform-decorators-legacy": "^1.3.4",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-polyfill": "^6.23.0",
"babel-preset-es2015": "^6.24.1",
"babel-preset-react": "^6.24.1",
"babel-preset-stage-0": "^6.24.1",
"babel-preset-stage-2": "^6.3.13",
"circular-dependency-plugin": "^3.0.0",
"classnames": "^2.2.5",
"clean-webpack-plugin": "^0.1.16",
"copy-webpack-plugin": "^4.0.1",
"css-loader": "^0.28.4",
"dotenv": "^4.0.0",
"es6-promise": "^4.1.1",
"file-loader": "^0.11.2",
"firebase": "^4.1.3",
"history": "^4.6.3",
"immutable": "^3.8.1",
"invariant": "^2.2.2",
"isomorphic-fetch": "^2.2.1",
"jsdom": "^11.1.0",
"jsonwebtoken": "^7.4.1",
"konva": "^1.6.3",
"less": "^2.3.1",
"less-loader": "^4.0.5",
"react": "^15.6.1",
"react-addons-css-transition-group": "^15.6.0",
"react-async-script": "^0.9.1",
"react-async-script-loader": "^0.3.0",
"react-bootstrap": "^0.31.1",
"react-dnd": "^2.4.0",
"react-dnd-html5-backend": "^2.4.1",
"react-dom": "^15.6.1",
"react-fontawesome": "^1.6.1",
"react-ga": "^2.2.0",
"react-google-recaptcha": "^0.9.6",
"react-gravatar": "^2.6.3",
"react-helmet": "^5.1.3",
"react-input-range": "^1.2.1",
"react-konva": "^1.1.3",
"react-modal": "^2.2.2",
"react-page-click": "^4.0.1",
"react-recaptcha": "^2.3.2",
"react-redux": "^5.0.5",
"react-router": "^3.0.2",
"react-router-redux": "^4.0.0",
"react-tag-input": "^4.7.2",
"react-toggle": "^4.0.1",
"redux": "^3.7.2",
"redux-form": "^7.0.1",
"redux-logger": "^2.3.2",
"redux-thunk": "^2.2.0",
"rimraf": "^2.6.1",
"single-module-instance-webpack-plugin": "0.0.4",
"style-loader": "^0.18.2",
"superagent": "^3.5.2",
"webpack": "^3.5.0",
"webpack-bundle-analyzer": "^2.9.0",
"xml2js": "^0.4.17",
"xmldom": "^0.1.27",
"xpath": "0.0.24"
},
"scripts": {
"start": "node devServer.js --progress --verbose",
"clean": "rimraf ./dist",
"dev": "webpack -d --watch --progress --display-error-details --display-reasons",
"start1": "webpack-dev-server --config ./webpack.config.comphotdeploy -d --progress --colors --host localhost --port 28080 --hot --inline --content-base src",
"builddev": "webpack -d --progress --display-error-details --display-reasons",
"build": "webpack -p --progress --verbose",
"dist": "rimraf ./dist&&webpack -d --display-error-details --display-reasons",
"start-react": "SET PORT=9999&&SET DEVTOOL=source-map&&react-scripts start",
"build-react": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": "./node_modules/react-scripts/config/eslint.js"
}
}
当我构建在线部署时,我正在使用命令
npm run build
webpack.config.js
var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
var webpack = require('webpack');
var path = require('path');
var ProvidePlugin = require("webpack/lib/ProvidePlugin");
var CommonsChunkPlugin = require("webpack/lib/optimize/CommonsChunkPlugin");
var LimitChunkCountPlugin = require("webpack/lib/optimize/LimitChunkCountPlugin");
var DedupePlugin = require("webpack/lib/optimize/DedupePlugin");
var SingleModuleInstancePlugin = require('single-module-instance-webpack-plugin');
var CleanWebpackPlugin = require('clean-webpack-plugin');
var CopyWebpackPlugin = require('copy-webpack-plugin');
var CircularDependencyPlugin = require('circular-dependency-plugin');
//var BUILD_DIR = path.resolve(__dirname,'/opt/glassfish/glassfish/domains/domain1/applications/Client/html');
var BUILD_DIR = path.resolve(__dirname,'dist');
var APP_DIR = path.resolve(__dirname, 'src');
var CLIENT_DIR = path.resolve(__dirname, 'src/client');
// Load environment variables from .env file. Suppress warnings using silent
// if this file is missing. dotenv will never modify any environment variables
// that have already been set.
// https://github.com/motdotla/dotenv
require('dotenv').config({silent: true});
var PrintChunksPlugin = function() {};
PrintChunksPlugin.prototype.apply = function(compiler) {
compiler.plugin('compilation', function(compilation, params) {
compilation.plugin('after-optimize-chunk-assets', function(chunks) {
console.log(chunks.map(function(c) {
return {
id: c.id,
name: c.name
/*,
includes: c.modules.map(function(m) {
return m.request;
})
*/
};
}));
});
});
};
var config = {
devtool: 'cheap-module-source-map',
entry: {
app: APP_DIR + '/index.js'
},
output: {
path:BUILD_DIR,
filename: "[name].bundle.js",
sourceMapFilename: "[name].bundle.js.map",
chunkFilename: "[name]-chunk.js",
//publicPath: BUILD_DIR
},
watch: false,
watchOptions: {
poll: true,
aggregateTimeout: 300,
number: 1000
},
module : {
loaders : [
{
test : /\.jsx?/,
include : APP_DIR,
exclude: /node_modules/,
loaders: ['react-hot-loader', 'babel-loader?' + JSON.stringify({
cacheDirectory: true,
plugins: [
'transform-runtime',
'react-html-attrs',
'transform-class-properties',
'transform-decorators-legacy'
],
presets: [
[
"es2015",
{
"modules": false
}
],
'react',
'stage-2']
})]
},
// CSS
// "postcss" loader applies autoprefixer to our CSS.
// "css" loader resolves paths in CSS and adds assets as dependencies.
// "style" loader turns CSS into JS modules that inject <style> tags.
// In production, we use a plugin to extract that CSS to a file, but
// in development "style" loader enables hot editing of CSS.
{
test: /\.css$/,
include: path.join(__dirname, 'src/style'),
loader: 'style-loader!css-loader'
},
// "file" loader makes sure those assets get served by WebpackDevServer.
// When you `import` an asset, you get its (virtual) filename.
// In production, they would get copied to the `build` folder.
{
test: /\.(ico|jpg|png|gif|eot|otf|webp|svg|ttf|woff|woff2)(\?.*)?$/,
exclude: /\/favicon.ico$/,
loader: 'file-loader',
query: {
name: '[path][name][hash].[ext]',
publicPath: '/'
}
},
{
test: /\.(ico)(\?.*)?$/,
exclude: /node_modules/,
loader: 'file-loader',
query: {
name: './images/[name].[ext]'
}
},
{
test: /\.xml$/,
loader: 'file-loader',
query: {
name: './[name].[ext]'
}
},
]
},
// use EnableCircularDependencyPlugin=true|false to check the option
plugins: (function() {
var plugins = [
new webpack.DefinePlugin({
// A common mistake is not stringifying the "production" string.
'process.env': { 'NODE_ENV': JSON.stringify('production') },
// DISABLE redux-devtools HERE
__DEVTOOLS__: false
}),
new CopyWebpackPlugin([
{ from: APP_DIR + '/index.html', to: BUILD_DIR + '/index.html' },
{ from: APP_DIR + '/sitemap.xml', to: BUILD_DIR + '/sitemap.xml' },
{ from: APP_DIR + '/Robots.txt', to: BUILD_DIR + '/Robots.txt' },
{ from: APP_DIR + '/images/favicon.ico', to: BUILD_DIR + '/images/favicon.ico' },
{ from: APP_DIR + '/images/favicon.png', to: BUILD_DIR + '/images/favicon.png' },
{ from: APP_DIR + '/images/favicon-16x16.png', to: BUILD_DIR + '/images/favicon-16x16.png' },
{ from: APP_DIR + '/images/favicon-32x32.png', to: BUILD_DIR + '/images/favicon-32x32.png' },
{ from: APP_DIR + '/images/favicon-48x48.png', to: BUILD_DIR + '/images/favicon-48x48.png' },
{ from: APP_DIR + '/images/favicon-57x57.png', to: BUILD_DIR + '/images/favicon-57x57.png' },
{ from: APP_DIR + '/images/favicon-60x60.png', to: BUILD_DIR + '/images/favicon-60x60.png' },
{ from: APP_DIR + '/images/favicon-72x72.png', to: BUILD_DIR + '/images/favicon-72x72.png' },
{ from: APP_DIR + '/images/favicon-76x76.png', to: BUILD_DIR + '/images/favicon-76x76.png' },
{ from: APP_DIR + '/images/favicon-96x96.png', to: BUILD_DIR + '/images/favicon-96x96.png' },
{ from: APP_DIR + '/images/favicon-114x114.png', to: BUILD_DIR + '/images/favicon-114x114.png' },
{ from: APP_DIR + '/images/favicon-120x120.png', to: BUILD_DIR + '/images/favicon-120x120.png' },
{ from: APP_DIR + '/images/favicon-144x144.png', to: BUILD_DIR + '/images/favicon-144x144.png' },
{ from: APP_DIR + '/images/favicon-152x152.png', to: BUILD_DIR + '/images/favicon-152x152.png' },
{ from: APP_DIR + '/images/favicon-160x160.png', to: BUILD_DIR + '/images/favicon-160x160.png' },
{ from: APP_DIR + '/images/favicon-180x180.png', to: BUILD_DIR + '/images/favicon-180x180.png' },
{ from: APP_DIR + '/images/favicon-192x192.png', to: BUILD_DIR + '/images/favicon-192x192.png' }
]),
new webpack.HotModuleReplacementPlugin(),
new webpack.NoEmitOnErrorsPlugin(),
new BundleAnalyzerPlugin({analyzerMode: 'static'}),
//new PrintChunksPlugin()
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: function (module) {
// this assumes your vendor imports exist in the node_modules directory
return module.context && module.context.indexOf('node_modules') !== -1;
}
}),
//CommonChunksPlugin will now extract all the common modules from vendor and main bundles
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest' //But since there are no more common modules between them we end up with just the runtime code included in the manifest file
}),
];
// HERE IS OPTION CONDITION
// edit .env file change to EnableCircularDependencyPlugin=false will bypass it
if (process.env.EnableCircularDependencyPlugin=="true") {
plugins.push(new CircularDependencyPlugin({
// exclude detection of files based on a RegExp
exclude: /a\.js|node_modules/,
// add errors to webpack instead of warnings
failOnError: true
}));
}
return plugins;
})(),
node: {
net: 'empty',
dns: 'empty'
}
};
module.exports = config;
的index.html
<!doctype html>
<html>
<head>
</head>
<body>
<div id="app"></div>
<script src="manifest.bundle.js"></script>
<script src="vendor.bundle.js" ></script>
<script src="app.bundle.js" ></script>
</body>
</html>
编译完成后,我最终得到以下文件:
另一件奇怪的事情是,我可以在A-chunk.js中看到一些只应该在B-Chunk.js中的文件。
我的猜测是vendo.bundle.js因为它的大小而减慢了初始加载速度。
真实文件(我部署的文件)的大小是Parsed大小,而不是Gzip大小。 看起来gzip压缩没有开始。
这就是我不知道为什么它不会自动完成的原因。 是否有一个命令可以执行/添加以自动获取gzip压缩文件,还是我应该手动执行的步骤?
取得了一些进展。
在webpack.config.js中我添加了以下内容:
var CompressionPlugin = require('compression-webpack-plugin');
和
new CompressionPlugin({
asset: "[path].gz[query]",
algorithm: "gzip",
test: /\.js$|\.css$|\.html$/,
threshold: 10240,
minRatio: 0.8
})
所以现在我生成了js和js.gz文件。
我还更新了我的web.config以添加以下内容:
<httpCompression directory="%SystemDrive%\inetpub\temp\IIS Temporary Compressed Files">
<scheme name="gzip" dll="%Windir%\system32\inetsrv\gzip.dll"/>
<dynamicTypes>
<add mimeType="text/*" enabled="true"/>
<add mimeType="message/*" enabled="true"/>
<add mimeType="application/javascript" enabled="true"/>
<add mimeType="*/*" enabled="false"/>
</dynamicTypes>
<staticTypes>
<add mimeType="text/*" enabled="true"/>
<add mimeType="message/*" enabled="true"/>
<add mimeType="application/javascript" enabled="true"/>
<add mimeType="*/*" enabled="false"/>
</staticTypes>
</httpCompression>
<urlCompression doStaticCompression="true" doDynamicCompression="true"/>
但到目前为止,这并没有改变任何事情。据我所知,gz文件没有加载。 (我正在使用https://varvy.com/pagespeed/来测试更改)
接下来我尝试编写一组IIS规则来返回.js.gz文件。 但由于我不是一个专业的IIS,我没有取得很好的成果使它工作......
这是我到目前为止所做的:
<rewrite>
<rules>
<rule name="Return gzip" stopProcessing="true">
<match url="^.*\.(js)$" />
<action type="Rewrite" url="{R:1}.gz" />
</rule>
</rules>
</rewrite>
但我认为我需要一种方法将标题内容类型更改为gzip才能使其正常工作。 只是不确定该怎么做......
答案 0 :(得分:0)
我需要帮助才能找到我做错的事情并减慢加载时间。
优化SPA应用程序有不同的方法,包括加载时间,带宽量和性能,而定型解决方案是创建一个复合/多块包并优化&amp;压缩它。
但是现代浏览器的ES8 +时代,有一个新的最佳解决方案:使用原生ES6模块,并部署具有此类用途的应用程序。请参阅以下文章:https://philipwalton.com/articles/deploying-es2015-code-in-production-today/和https://www.contentful.com/blog/2017/04/04/es6-modules-support-lands-in-browsers-is-it-time-to-rethink-bundling/。这种方法可以提高性能并减少服务器负载。