浅谈如何使用 webpack 优化资源

前言

在前端应用的优化中,对加载资源的大小控制极其的重要,大多数时候我们能做的是在打包编译的过程对资源进行大小控制、拆分与复用。

本片文章中主要是基于 webpack 打包,以 React、vue 等生态开发的单页面应用来举例说明如何从 webpack 打包的层面去处理资源以及缓存,其中主要我们需要做的是对 webpack 进行配置的优化,同时涉及少量的业务代码的更改。

同时对打包资源的分析可以使用 (webpack-contrib/webpack-bundle-analyzer) 插件,当然可选的分析插件还是很多的,在本文中主要以该插件来举例分析。

TIP: webpack 版本 @3.6.0

一、打包环境与代码压缩

首先我们有一个最基本的 webpack 配置:

// webpack.config.js
const path = require('path');
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;

const PROJECT_ROOT = path.resolve(__dirname, './');

module.exports = {
 entry: {
  index: './src/index.js'
 },
 output: {
  path: path.resolve(__dirname, 'dist'),
  filename: '[name].[chunkhash:4].js'
 },
 module: {
  rules: [
   {
    test: /\.js[x]?$/,
    use: 'babel-loader',
    include: PROJECT_ROOT,
    exclude: /node_modules/
   }
  ]
 },
 plugins: [
  new BundleAnalyzerPlugin()
 ],
 resolve: {
  extensions: ['.js', '.jsx']
 },
};

执行打包可以看到一个项目的 js 有 1M 以上:

Hash: e51afc2635f08322670b
Version: webpack 3.6.0
Time: 2769ms
    Asset  Size Chunks          Chunk Names
index.caa7.js 1.3 MB    0 [emitted] [big] index

这时候只需要增加插件 `DefinePlugin` 与 `UglifyJSPlugin` 即可减少不少的体积,在 plugins 中添加:

// webpack.config.js
...
{
 ...
 plugins: [
  new BundleAnalyzerPlugin(),
  new webpack.DefinePlugin({
   'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'production')
  }),
  new UglifyJSPlugin({
   uglifyOptions: {
    ie8: false,
    output: {
     comments: false,
     beautify: false,
    },
    mangle: {
     keep_fnames: true
    },
    compress: {
     warnings: false,
     drop_console: true
    },
   }
  })
 ]
 ...
}

可以看到这时候的打包输出:

Hash: 84338998472a6d3c5c25
Version: webpack 3.6.0
Time: 9940ms
    Asset  Size Chunks          Chunk Names
index.89c2.js 346 kB    0 [emitted] [big] index

代码的大小从 1.3M 降到了 346K。

(1)DefinePlugin

DefinePlugin 允许创建一个在编译时可以配置的全局常量。这可能会对开发模式和发布模式的构建允许不同的行为非常有用。如果在开发构建中,而不在发布构建中执行日志记录,则可以使用全局常量来决定是否记录日志。这就是 DefinePlugin 的用处,设置它,就可以忘记开发和发布构建的规则。

在我们的业务代码和第三方包的代码中很多时候需要判断 `process.env.NODE_ENV` 来做不同处理,而在生产环境中我们显然不需要非 `production` 的处理部分。

在这里我们设置 `process.env.NODE_ENV` 为 `JSON.stringify('production')`,也就是表示讲打包环境设置为生产环境。之后配合 `UglifyJSPlugin` 插件就可以在给生产环境打包的时候去除部分的冗余代码。

(2)UglifyJSPlugin

UglifyJSPlugin 主要是用于解析、压缩 js 代码,它基于 `uglify-es` 来对 js 代码进行处理,它有多种配置选项:https://github.com/webpack-contrib/uglifyjs-webpack-plugin

通过对代码的压缩处理以及去除冗余,大大减小了打包资源的体积大小。

二、代码拆分/按需加载

在如 React 或者 vue 构建的单页面应用中,对页面路由与视图的控制是由前端来实现的,其对应的业务逻辑都在 js 代码中。

当一个应用设计的页面和逻辑很多的时候,最终生成的 js 文件资源也会相当大。

然而当我们打开一个 url 对应的页面时,实际上需要的并非全部的 js 代码,所需要的仅是一个主的运行时代码与该视图对应的业务逻辑的代码,在加载下一个视图的时候再去加载那部分的代码。

因此,对这方面可做的优化就是对 js 代码进行按需加载。

懒加载或者按需加载,是一种很好的优化网页或应用的方式。这种方式实际上是先把你的代码在一些逻辑断点处分离开,然后在一些代码块中完成某些操作后,立即引用或即将引用另外一些新的代码块。这样加快了应用的初始加载速度,减轻了它的总体体积,因为某些代码块可能永远不会被加载。

在 webpack 中提供了动态导入的技术来实现代码拆分,首先在 webpack 的配置中需要去配置拆分出来的每个子模块的配置:

// webpack.config.js
const path = require('path');
const webpack = require('webpack');
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;

const PROJECT_ROOT = path.resolve(__dirname, './');

module.exports = {
 entry: {
  index: './src/index.js'
 },
 output: {
  path: path.resolve(__dirname, 'dist'),
  filename: '[name].[chunkhash:4].js',
  chunkFilename: '[name].[chunkhash:4].child.js',
 },
 module: {
  rules: [
   {
    test: /\.js[x]?$/,
    use: 'babel-loader',
    include: PROJECT_ROOT,
    exclude: /node_modules/
   }
  ]
 },
 plugins: [
  new BundleAnalyzerPlugin(),
  new webpack.DefinePlugin({
   'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'production')
  }),
  new UglifyJSPlugin({
   uglifyOptions: {
    ie8: false,
    output: {
     comments: false,
     beautify: false,
    },
    mangle: {
     keep_fnames: true
    },
    compress: {
     warnings: false,
     drop_console: true
    },
   }
  }),
 ],
 resolve: {
  extensions: ['.js', '.jsx']
 },
};

其中主要需要定义的则是 `output` 中的 `chunkFilename`,它是导出的拆分代码的文件名,这里给它设置为 `[name].[chunkhash:4].child.js`,其中的 `name` 对应模块名称或者 id,`chunkhash` 是模块内容的 hash。

之后在业务代码中 webpack 提供了两种方式来动态导入:

  • `import('path/to/module') -> Promise`,
  • `require.ensure(dependencies: String[], callback: function(require), errorCallback: function(error), chunkName: String)`

对于最新版本的 webpack 主要推荐使用 `import()` 的方式(注意:import 使用到了 Promise,因此需要确保代码中支持了 Promise 的 polyfill)。

// src/index.js
function getComponent() {
 return import(
  /* webpackChunkName: "lodash" */
  'lodash'
 ).then(_ => {
  var element = document.createElement('div');

  element.innerHTML = _.join(['Hello', 'webpack'], ' ');

  return element;

 }).catch(error => 'An error occurred while loading the component');
}

getComponent().then(component => {
 document.body.appendChild(component);
})

可以看到打包的信息:

Hash: d6ba79fe5995bcf9fa4d
Version: webpack 3.6.0
Time: 7022ms
        Asset   Size Chunks       Chunk Names
lodash.89f0.child.js 85.4 kB    0 [emitted] lodash
    index.316e.js 1.96 kB    1 [emitted] index
  [0] ./src/index.js 441 bytes {1} [built]
  [2] (webpack)/buildin/global.js 509 bytes {0} [built]
  [3] (webpack)/buildin/module.js 517 bytes {0} [built]
  + 1 hidden module

可以看到打包出来的代码生成了 `index.316e.js` 和 `lodash.89f0.child.js` 两个文件,后者则是通过 `import` 来实现拆分的。

`import` 它接收一个 `path` 参数,指的是该子模块对于的路径,同时还注意到其中可以添加一行注释 `/* webpackChunkName: "lodash" */`,该注释并非是无用的,它定义了该子模块的 name,其对应与 `output.chunkFilename` 中的 `[name]`。

`import` 函数返回一个 Promise,当异步加载到子模块代码是会执行后续操作,比如更新视图等。

(1)React 中的按需加载

在 React 配合 React-Router 开发中,往往就需要代码根据路由按需加载的能力,下面是一个基于 webpack 代码动态导入技术实现的 React 动态载入的组件:

import React, { Component } from 'react';

export default function lazyLoader (importComponent) {
 class AsyncComponent extends Component {
  state = { Component: null }

  async componentDidMount () {
   const { default: Component } = await importComponent();

   this.setState({
    Component: Component
   });
  }

  render () {
   const Component = this.state.Component;

   return Component
    ? <Component {...this.props} />
    : null;
  }
 }

 return AsyncComponent;
};

在 `Route` 中:

<Switch>
 <Route exact path="/"
  component={lazyLoader(() => import('./Home'))}
 />
 <Route path="/about"
  component={lazyLoader(() => import('./About'))}
 />
 <Route
  component={lazyLoader(() => import('./NotFound'))}
 />
</Switch>

在 `Route` 中渲染的是 `lazyLoader` 函数返回的组件,该组件在 mount 之后会去执行 `importComponent` 函数(既:`() => import('./About')`)动态加载其对于的组件模块(被拆分出来的代码),待加载成功之后渲染该组件。

使用该方式打包出来的代码:

Hash: 02a053d135a5653de985
Version: webpack 3.6.0
Time: 9399ms
     Asset   Size Chunks          Chunk Names
0.db22.child.js 5.82 kB    0 [emitted]
1.fcf5.child.js  4.4 kB    1 [emitted]
2.442d.child.js   3 kB    2 [emitted]
 index.1bbc.js  339 kB    3 [emitted] [big] index

三、抽离 Common 资源

(1)第三方库的长缓存

首先对于一些比较大的第三方库,比如在 React 中用到的 react、react-dom、react-router 等等,我们不希望它们被重复打包,并且在每次版本更新的时候也不希望去改变这部分的资源导致在用户端重新加载。

在这里可以使用 webpack 的 CommonsChunkPlugin 来抽离这些公共资源;

CommonsChunkPlugin 插件,是一个可选的用于建立一个独立文件(又称作 chunk)的功能,这个文件包括多个入口 chunk 的公共模块。通过将公共模块拆出来,最终合成的文件能够在最开始的时候加载一次,便存起来到缓存中供后续使用。这个带来速度上的提升,因为浏览器会迅速将公共的代码从缓存中取出来,而不是每次访问一个新页面时,再去加载一个更大的文件。
首先需要在 entry 中新增一个入口用来打包需要抽离出来的库,这里将 `'react', 'react-dom', 'react-router-dom', 'immutable'` 都给单独打包进 `vendor` 中;

之后在 plugins 中定义一个 `CommonsChunkPlugin` 插件,同时将其 `name` 设置为 `vendor` 是它们相关联,再将 `minChunks` 设置为 `Infinity` 防止其他代码被打包进来。

// webpack.config.js
const path = require('path');
const webpack = require('webpack');
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;

const PROJECT_ROOT = path.resolve(__dirname, './');

module.exports = {
 entry: {
  index: './src0/index.js',
  vendor: ['react', 'react-dom', 'react-router-dom', 'immutable']
 },
 output: {
  path: path.resolve(__dirname, 'dist'),
  filename: '[name].[chunkhash:4].js',
  chunkFilename: '[name].[chunkhash:4].child.js',
 },
 module: {
  rules: [
   {
    test: /\.js[x]?$/,
    use: 'babel-loader',
    include: PROJECT_ROOT,
    exclude: /node_modules/
   }
  ]
 },
 plugins: [
  new BundleAnalyzerPlugin(),
  new webpack.DefinePlugin({
   'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'production')
  }),
  new UglifyJSPlugin({
   uglifyOptions: {
    ie8: false,
    output: {
     comments: false,
     beautify: false,
    },
    mangle: {
     keep_fnames: true
    },
    compress: {
     warnings: false,
     drop_console: true
    },
   }
  }),
  new webpack.optimize.CommonsChunkPlugin({
   name: 'vendor',
   minChunks: Infinity,
  }),
 ],
 resolve: {
  extensions: ['.js', '.jsx']
 },
};

运行打包可以看到:

Hash: 34a71fcfd9a24e810c21
Version: webpack 3.6.0
Time: 9618ms
     Asset   Size Chunks          Chunk Names
0.2c65.child.js 5.82 kB    0 [emitted]
1.6e26.child.js  4.4 kB    1 [emitted]
2.e4bc.child.js   3 kB    2 [emitted]
 index.4e2f.js 64.2 kB    3 [emitted]     index
 vendor.5fd1.js  276 kB    4 [emitted] [big] vendor

可以看到 `vendor` 被单独打包出来了。

当我们改变业务代码时再次打包:

Hash: cd3f1bc16b28ac97e20a
Version: webpack 3.6.0
Time: 9750ms
     Asset   Size Chunks          Chunk Names
0.2c65.child.js 5.82 kB    0 [emitted]
1.6e26.child.js  4.4 kB    1 [emitted]
2.e4bc.child.js   3 kB    2 [emitted]
 index.4d45.js 64.2 kB    3 [emitted]     index
 vendor.bc85.js  276 kB    4 [emitted] [big] vendor

vendor 包同样被打包出来的,然而它的文件 hash 却发生了变化,这显然不符合我们长缓存的需求。

这是因为 webpack 在使用 CommoChunkPlugin 的时候会生成一段 runtime 代码(它主要用来处理代码模块的映射关系),而哪怕没有改变 vendor 里的代码,这个 runtime 仍然是会跟随着打包变化的并且打入 verdor 中,所以 hash 就会开始变化了。解决方案则是把这部分的 runtime 代码也单独抽离出来,修改之前的 `CommonsChunkPlugin` 为:

// webpack.config.js
...
new webpack.optimize.CommonsChunkPlugin({
 name: ['vendor', 'runtime'],
 minChunks: Infinity,
}),
...

执行打包可以看到生成的代码中多了 `runtime` 文件,同时即使改变业务代码,vendor 的 hash 值也保持不变了。

当然这段 `runtime` 实际上非常短,我们可以直接 inline 在 html 中,如果使用的是 `html-webpack-plugin` 插件处理 html,则可以结合 [`html-webpack-inline-source-plugin`](DustinJackson/html-webpack-inline-source-plugin) 插件自动处理其 inline。

(2)公共资源抽离

在我们打包出来的 js 资源包括不同入口以及子模块的 js 资源包,然而它们之间也会重复载入相同的依赖模块或者代码,因此可以通过 CommonsChunkPlugin 插件将它们共同依赖的一些资源打包成一个公共的 js 资源。

// webpack.config.js
plugins: [
 new BundleAnalyzerPlugin(),
 new webpack.DefinePlugin({
  'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'production')
 }),
 new UglifyJSPlugin({
  uglifyOptions: {
   ie8: false,
   output: {
    comments: false,
    beautify: false,
   },
   mangle: {
    keep_fnames: true
   },
   compress: {
    warnings: false,
    drop_console: true
   },
  }
 }),
 new webpack.optimize.CommonsChunkPlugin({
  name: ['vendor', 'runtime'],
  minChunks: Infinity,
 }),
 new webpack.optimize.CommonsChunkPlugin({
  // ( 公共chunk(commnons chunk) 的名称)
  name: "commons",
  // ( 公共chunk 的文件名)
  filename: "commons.[chunkhash:4].js",
  // (模块必须被 3个 入口chunk 共享)
  minChunks: 3
 })
],

可以看到这里增加了 `commons` 的一个打包,当一个资源被三个以及以上 chunk 依赖时,这些资源会被单独抽离打包到 `commons.[chunkhash:4].js` 文件。

执行打包,看到结果如下:

Hash: 2577e42dc5d8b94114c8
Version: webpack 3.6.0
Time: 24009ms
     Asset   Size Chunks          Chunk Names
0.2eee.child.js 90.8 kB    0 [emitted]
1.cfbc.child.js 89.4 kB    1 [emitted]
2.557a.child.js  88 kB    2 [emitted]
 vendor.66fd.js  275 kB    3 [emitted] [big] vendor
 index.688b.js 64.2 kB    4 [emitted]     index
commons.a61e.js 1.78 kB    5 [emitted]     commons

却发现这里的 `commons.[chunkhash].js` 基本没有实际内容,然而明明在每个子模块中也都依赖了一些相同的依赖。

借助 webpack-bundle-analyzer 来分析一波:

可以看到三个模块都依赖了 `lodash`,然而它并没有被抽离出来。

这是因为 CommonsChunkPlugin 中的 chunk 指的是 entry 中的每个入口,因此对于一个入口拆分出来的子模块(children chunk)是不生效的。

可以通过在 CommonsChunkPlugin 插件中配置 `children` 参数将拆分出来的子模块的公共依赖也打包进 `commons` 中:

// webpack.config.js
plugins: [
 new BundleAnalyzerPlugin(),
 new webpack.DefinePlugin({
  'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'production')
 }),
 new UglifyJSPlugin({
  uglifyOptions: {
   ie8: false,
   output: {
    comments: false,
    beautify: false,
   },
   mangle: {
    keep_fnames: true
   },
   compress: {
    warnings: false,
    drop_console: true
   },
  }
 }),
 new webpack.optimize.CommonsChunkPlugin({
  name: ['vendor', 'runtime'],
  minChunks: Infinity,
 }),
 new webpack.optimize.CommonsChunkPlugin({
  // ( 公共chunk(commnons chunk) 的名称)
  name: "commons",
  // ( 公共chunk 的文件名)
  filename: "commons.[chunkhash:4].js",
  // (模块必须被 3个 入口chunk 共享)
  minChunks: 3
 }),
 new webpack.optimize.CommonsChunkPlugin({
  // (选择所有被选 chunks 的子 chunks)
  children: true,
  // (在提取之前需要至少三个子 chunk 共享这个模块)
  minChunks: 3,
 })
],

查看打包效果:

其子模块的公共资源都被打包到 `index` 之中了,并没有理想地打包进 `commons` 之中,还是因为 `commons` 对于的是 entry 中的入口模块,而这里并未有 3 个 entry 模块共用资源;

在单入口的应用中可以选择去除 `commons`,而在子模块的 `CommonsChunkPlugin` 的配置中配置 `async` 为 `true`:

// webpack.config.js
plugins: [
 new BundleAnalyzerPlugin(),
 new webpack.DefinePlugin({
  'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'production')
 }),
 new UglifyJSPlugin({
  uglifyOptions: {
   ie8: false,
   output: {
    comments: false,
    beautify: false,
   },
   mangle: {
    keep_fnames: true
   },
   compress: {
    warnings: false,
    drop_console: true
   },
  }
 }),
 new webpack.optimize.CommonsChunkPlugin({
  name: ['vendor', 'runtime'],
  minChunks: Infinity,
 }),
 new webpack.optimize.CommonsChunkPlugin({
  // (选择所有被选 chunks 的子 chunks)
  children: true,
  // (异步加载)
  async: true,
  // (在提取之前需要至少三个子 chunk 共享这个模块)
  minChunks: 3,
 })
],

查看效果:

子模块的公共资源都被打包到 `0.9c90.child.js` 中了,该模块则是子模块的 commons。

四、tree shaking

tree shaking 是一个术语,通常用于描述移除 JavaScript 上下文中的未引用代码(dead-code)。它依赖于 ES2015 模块系统中的静态结构特性,例如 import 和 export。这个术语和概念实际上是兴起于 ES2015 模块打包工具 rollup。
在我们引入一个依赖的某个输出的时候,我们可能需要的仅仅是该依赖的某一部分代码,而另一部分代码则是 `unused` 的,如果能够去除这部分代码,那么最终打包出来的资源体积也是可以有可观的减小。

首先,webpack 中实现 tree shaking 是基于 webpack 内部支持的 es2015 的模块机制,在大部分时候我们使用 babel 来编译 js 代码,而 babel 会通过自己的模块加载机制处理一遍,这导致 webpack 中的 tree shaking 处理将会失效。因此在 babel 的配置中需要关闭对模块加载的处理:

// .babelrc
{
 "presets": [
  [
   "env", {
    "modules": false,
   }
  ],
  "stage-0"
 ],
 ...
}

然后我们来看下 webpack 是如何处理打包的代码,举例有一个入口文件 `index.js` 和一个 `utils.js` 文件:

// utils.js
export function square(x) {
 return x * x;
}

export function cube(x) {
 return x * x * x;
}
```

```js
// index.js
import { cube } from './utils.js';

console.log(cube(10));
```

打包出来的代码:

```
// index.bundle.js
/* 1 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
/* unused harmony export square */
/* harmony export (immutable) */ __webpack_exports__["a"] = cube;
function square(x) {
 return x * x;
}

function cube(x) {
 return x * x * x;
}

可以看到仅有 `cube` 函数被 `__webpack_exports__` 导出来,而 `square` 函数被标记为 `unused harmony export square`,然而在打包代码中既是 `square` 没有被导出但是它仍然存在与代码中,而如何去除其代码则可以通过添加 `UglifyjsWebpackPlugin` 插件来处理。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 浅析webpack 如何优雅的使用tree-shaking(摇树优化)

    1.什么是tree-shaking webpack 2 的到来带来的最棒的新特性之一就是tree-shaking .tree-shaking源自于rollup.js,先如今,webpack 2也有类似的做法. webpack 里的tree-shaking的到来不得不归功于es6规范的模块.为什么这么说,如今的前端模块规范很多,比较出流行的比如commonJS , AMD , es6 ,我简单的说一下commonJS和es6模块的区别. commonJS 模块 commonJS的模块规范在Node

  • 详解vue项目优化之按需加载组件-使用webpack require.ensure

    使用 vue-cli构建的项目,在 默认情况下 ,执行 npm run build  会将所有的js代码打包为一个整体, 打包位置是 dist/static/js/app.[contenthash].js 类似下面的路由代码 router/index.js  路由相关信息,该路由文件引入了多个 .vue组件 import Hello from '@/components/Hello' import Province from '@/components/Province' import Segm

  • 详解vue-cli + webpack 多页面实例配置优化方法

    本文介绍了vue-cli + webpack 多页面实例配置优化方法,分享给大家 vue+webpack是否有多页面 目前使用vue来做项目,估计大部分都是单页面(SPA)应用,一个轻型的 MVVM 框架,谁用了MVVM框架,就再也回不去JQ时代了,哈哈. 在手机端的项目,使用vue + vue-router是high到爆,不仅仅是我们开发的而言,最主要的用户体检也是开足马力,体检感杠杠的. 那问题来了,使用vue+webpack的单页面是爽到爆,那如果是多页面也能不能high到爆呢?那当然呀,

  • webpack学习笔记之优化缓存、合并、懒加载

    除了的webpack基本配置,还可以进一步添加配置,优化合并文件,加快编译速度.下面是生产环境配置文件webpack.production.js,与wenbpack.config.js相比其不需要一些dev-tools,dev-server和jshint校验等,将与开发相关的东西删掉.下面的介绍均以此代码配置作参考. /*生成环境配置文件:不需要一些dev-tools,dev-server和jshint校验等.和开发有关的东西删掉*/ var webpack = require('webpack

  • Webpack性能优化 DLL 用法详解

    前言 在用 Webpack 打包的时候,对于一些不经常更新的第三方库,比如 react,lodash,我们希望能和自己的代码分离开,Webpack 社区有两种方案 CommonsChunkPlugin DLLPlugin 对于 CommonsChunkPlugin,webpack 每次打包实际还是需要去处理这些第三方库,只是打包完之后,能把第三方库和我们自己的代码分开.而DLLPlugin 则是能把第三方代码完全分离开,即每次只打包项目自身的代码. 用法 要使用 DLLPlugin,需要额外新建

  • 浅谈如何使用 webpack 优化资源

    前言 在前端应用的优化中,对加载资源的大小控制极其的重要,大多数时候我们能做的是在打包编译的过程对资源进行大小控制.拆分与复用. 本片文章中主要是基于 webpack 打包,以 React.vue 等生态开发的单页面应用来举例说明如何从 webpack 打包的层面去处理资源以及缓存,其中主要我们需要做的是对 webpack 进行配置的优化,同时涉及少量的业务代码的更改. 同时对打包资源的分析可以使用 (webpack-contrib/webpack-bundle-analyzer) 插件,当然可

  • 浅谈react+es6+webpack的基础配置

    这是模块化开发.主流框架和最新版的ECMAScript语法规范的一个小demo 准备工作 安装 nodeJs 首先进入node官网,去下载最新版的nodeJs webpack 安装webpack npm install webpack -g 参数-g表示全局安装webpack,你在cmd命令中哪个文件夹下都可以使用webpack的命令,如果不加-g的话,是只可以在你安装webpack的目录下使用webpack这个命令 webpack 也有一个 web 服务器 npm install webpac

  • 浅谈一下Nginx性能优化

    目录 Nginx 性能优化 1.Nginx运行工作进程数量 2.Nginx运行CPU亲和力 3.Nginx最大打开文件数 4.Nginx事件处理模型 5.开启高效传输模式 6.连接超时时间 7.fastcgi 调优 8.gzip 调优 9.expires 缓存调优 10.防盗链 11.内核参数优化 12.关于系统连接数的优化 Nginx 性能优化 1.Nginx运行工作进程数量 Nginx运行工作进程个数一般设置CPU的核心或者核心数x2.如果不了解cpu的核数,可以top命令之后按1看出来,也

  • 浅谈Pytorch torch.optim优化器个性化的使用

    一.简化前馈网络LeNet import torch as t class LeNet(t.nn.Module): def __init__(self): super(LeNet, self).__init__() self.features = t.nn.Sequential( t.nn.Conv2d(3, 6, 5), t.nn.ReLU(), t.nn.MaxPool2d(2, 2), t.nn.Conv2d(6, 16, 5), t.nn.ReLU(), t.nn.MaxPool2d(2

  • 浅谈MySQL大表优化方案

    背景 阿里云RDS FOR MySQL(MySQL5.7版本)数据库业务表每月新增数据量超过千万,随着数据量持续增加,我们业务出现大表慢查询,在业务高峰期主业务表的慢查询需要几十秒严重影响业务 方案概述 一.数据库设计及索引优化 MySQL数据库本身高度灵活,造成性能不足,严重依赖开发人员的表设计能力以及索引优化能力,在这里给几点优化建议 时间类型转化为时间戳格式,用int类型储存,建索引增加查询效率 建议字段定义not null,null值很难查询优化且占用额外的索引空间 使用TINYINT类

  • 浅谈java是如何做资源回收补救的

    学习java的过程,我们经常谈论一个对象的回收,尤其是资源类型,如果没有显示的关闭,对象就被回收了,说明出现了资源泄漏.java本身为了防止这种情况,做了一些担保的方式,确保可以让未关闭的资源合理回收掉. finalize回收 finalize方式是java对象被回收时触发的一个方法.java的很多资源对象,都是在finalize中写了担保的方法. /** * Ensures that the <code>close</code> method of this file input

  • 浅谈MySQL之select优化方案

    目录 生活中的例子 慢查询 如何去优化 count limit 最大值最小值min&max 生活中的例子 我们是否看到过在公司中许多查询语句都是select * xxxx 心中的想法肯定是,别人写了select *,那我写吧,省去了不少麻烦事儿 慢查询 首先去思考,最基本的,是否我们使用的数据库插查询语句存在了访问的数据太多 其实大部分性能低的查询往往都可以通过减少访问的数据量来优化的 因为select * 会给服务器带来额外的I/O.内存和cpu的消耗 数据库中慢查询开销的三个指标 相应时间

  • 浅谈vue项目打包优化策略

    使用vue-cli部署生产包时,发现资源包很大,打包后的vendor.js达到了1.4M,这已经很大了,而且会影响到首屏加载.那么,怎么优化呢? 1.组件按需加载 这是首先可以优化的点.如果频繁使用了第三方组件/UI库,如我的项目中经常同时使用了 element-ui, mint-ui,echarts等组件库,如果全部引入,项目体积非常大,这时可以按需引入组件. 示例如下: 1.1 element-ui 首先,安装 babel-plugin-component: npm install babe

  • 浅谈如何使用webpack构建多页面应用

    前言 之前使用 vue2.x + webpack3.x 撸了一个 vue 单页脚手架 vue 版 spa 脚手架 有兴趣的同学可以看下,内附详细注释,适合刚学习 webpack 的童鞋. react 版 spa 脚手架 但在一些场景下,单页应用显然无法满足我们的需求,于是便有了 mulXc-cli 好了,废话不多说,进入正题!!!! 文件结构  ├── build 构建服务和webpack配置 ├──── build.js 构建全量压缩包 (打包项目) ├──── setting.js 多页面入

  • 浅谈vue加载优化策略

    vue.js是一个比较流行的前端框架,与react.js.angular.js相比来说,vue.js入手曲线更加流畅,不管掌握多少都可以快速上手.但是单页面应用也都有其弊病,有时候首屏加载慢的让人捏舌.今天我们以vue cli3.x来说一说如何行之有效的缓解此问题! 方法一 路由懒加载 首屏加载慢的原因无非就是单页面应用需要加载完整个路由表上的页面,而路由懒加载就是来解决这个问题的.如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就更加高效了.下面这个

随机推荐