likes
comments
collection
share

webpack优化首屏加载时间及流畅度的思路

作者站长头像
站长
· 阅读数 34

Webpack是一个非常强大的模块打包器。它的主要功能是将多个模块按照依赖关系进行合并打包,并生成最终的静态资源。但是,在打包过程中,我们也需要考虑一些优化策略以提高页面的首屏加载时间和流畅度。

一、减少打包体积

1.只打包需要的模块

Webpack通过使用require()函数来引入模块,但是它会将所有的模块都打包进入bundle.js文件中。这样就会导致bundle.js文件过大,从而影响页面的首屏加载时间。为了减少打包体积,我们可以使用Webpack提供的Tree Shaking来实现只打包需要的模块。

Tree Shaking是Webpack 2.0以上版本新增的优化功能。它能够根据代码的引用关系,删除无用的代码,从而减少打包后的文件大小。在Webpack中使用Tree Shaking非常简单,只需在配置文件中设置mode为production即可。

module.exports = {
  mode: "production",
  ...
}

2.压缩代码

除了只打包需要的模块外,我们还可以使用Webpack提供的UglifyJS插件来压缩JS代码。通过压缩代码,可以去掉不必要的空格、注释、换行符等,从而减小打包后的文件大小。

在Webpack中使用UglifyJS插件非常简单,只需在配置文件中添加如下代码:

const UglifyJSPlugin = require('uglifyjs-webpack-plugin');

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

二、使用缓存

1.使用缓存提高打包速度

每次修改代码后都要重新构建和打包,这样会耗费大量时间。为了提高打包速度和效率,我们可以使用Webpack的缓存功能。

通过使用cache-loader或hard-source-webpack-plugin插件,可以将每次打包生成的结果缓存起来,这样下次打包时就可以直接使用缓存结果,从而提高打包效率。

2.使用浏览器缓存加快页面加载速度

浏览器缓存可以避免重复访问服务器,从而提高页面的加载速度。我们可以通过在Webpack中设置output.chunkFilename和output.filename来控制静态资源的命名规则,并设置max-age等缓存策略。

module.exports = {
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].[hash:8].js',
    chunkFilename: '[name].[hash:8].js'
  },
  ...
}

三、优化图片加载

1.使用webpack的file-loader和url-loader进行图片处理

Webpack提供的file-loader和url-loader可以帮助我们对图片进行处理,将图片转化成base64编码并嵌入到html中,从而减少http请求次数,提高页面加载速度。

file-loader会将图片打包后生成一个url,url-loader会根据图片大小来决定是否将图片转为base64编码。

2.使用图片压缩工具对图片进行压缩

图片压缩工具可以帮助我们对图片进行压缩,从而减小图片的大小,提高页面加载速度。

四、优化代码分割

Webpack的Code Splitting功能可以将代码拆分成不同的块,从而减少每个页面需要加载的资源数量和文件大小。通过将公共代码提取出来,可以避免重复加载和下载。

1.使用SplitChunksPlugin插件进行代码分割

Webpack提供了一个SplitChunksPlugin插件来帮助我们进行代码分割。可以将公共的依赖模块抽取成chunk,并且将多个chunk之间的重复依赖提取成单独的chunk。

module.exports = {
  optimization: {
    splitChunks: {
      chunks: "all"
    }
  },
  ...
}

2.按需加载

按需加载可以实现资源动态加载,从而提高页面加载速度。通过使用React.lazy()函数或者import()语法,可以实现组件的按需加载。

五、使用CDN加速

使用CDN可以将静态资源部署到全球各地的节点上,从而实现跨域访问和加速静态资源请求的速度。 优化用户体验不光要压缩代码文件,还要提高网络的传输速度,通过 CDN 可以实现。

CDN:内容分发网络,通过把资源部署到世界各地,用户在访问时按照就近原则从离用户最近的服务器获取资源,从而加速资源的获取速度。

CDN 其实是通过优化物理链路层传输过程中的网速有限、丢包等问题来提升网速的,其大致原理可以如下: 因为 CDN 都有缓存,所以为了避免 CDN 缓存导致用户加载到老版本的问题,需要遵循以下规则:

  • 针对 HTML 文件:不开启任何缓存,不放入 CDN
  • 针对静态 JS 、CSS 、图片等文件:开启 CDN 和缓存,放入 CDN 服务器,并且给每一个文件名带入 Hash 值,避免文件重名导致访问到同名缓存废弃文件的问题
  • 介于浏览器对同一时刻、同一域名的请求个数有限制的状况,请求资源过多的话,可能导致加载文件被阻塞。所以,当同一时间加载资源过多时,我们可以针对不同的文件类型放入不同的 CDN 上

在Webpack中使用CDN非常简单,只需在配置文件中设置output.publicPath的值为CDN地址即可。

module.exports = {
  ...
  output: {
    publicPath: 'http://cdn.com/static/'
  },
  ...
}

Webpack 可以很方便地配置 CDN 来加速静态资源请求的速度。下面是一份详细的配置步骤:

  1. 在 output 中设置 publicPath

在 Webpack 配置文件中的 output 配置项中,设置 publicPath 的值为 CDN 地址。例如:

module.exports = {
  output: {
    publicPath: 'https://cdn.example.com/'
  }
}
  1. 配置 externals

可以通过配置 externals,将一些第三方库从打包文件中抽离出来,以便于在 HTML 文件中引入 CDN 资源。当使用 externals 时,需要在页面中手动引入对应的 CDN 资源。

module.exports = {
  externals: {
    jquery: 'https://cdn.example.com/jquery.min.js'
  }
}
  1. 使用插件 html-webpack-plugin

使用 html-webpack-plugin 插件,可以在打包后的 HTML 文件中自动插入对应的 CDN 资源链接。可以使用该插件的 publicPath 配置项来设置 CDN 地址。

const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  plugins: [
    new HtmlWebpackPlugin({
      filename: 'index.html',
      template: './src/index.html',
      minify: true,
      publicPath: 'https://cdn.example.com/'
    })
  ]
}
  1. 使用 copy-webpack-plugin

若存在一些与打包无关的静态资源,可以通过 copy-webpack-plugin 插件将其从源码目录复制到打包后的目录中,同时修改 HTML 文件中的引用路径为 CDN 地址。

const CopyWebpackPlugin = require('copy-webpack-plugin');

module.exports = {
  plugins: [
    new CopyWebpackPlugin({
      patterns: [
        {
          from: 'src/assets',
          to: 'assets',
          transformPath(targetPath) {
            return `${PUBLIC_PATH}${targetPath}`;
          }
        }
      ]
    })
  ]
}
  1. 设置 Cache-Control 和 Expires 响应头

在 CDN 配置中设置 Cache-Control 或 Expires 响应头,可以让浏览器在第一次请求时缓存资源,并在过期前使用本地缓存,从而减少重复请求数据。

例如,可以在 Nginx 中增加如下配置:

location /static/ {
  expires 1d;
  add_header Cache-Control "public";
  alias /www/static/;
}

以上是在 Webpack 中配置 CDN 加速的详细步骤。需要注意的是,在使用 CDN 时还需要考虑到资源版本控制、跨域访问等问题。

六、优化打包速度

1.使用HappyPack多线程打包

Webpack是单线程的,打包速度比较慢,通过使用HappyPack插件可以将Webpack的loader部分进行多线程并行处理,从而提高打包速度。

2.使用DLLPlugin进行预编译

DLLPlugin可以将第三方库先进行打包,然后在开发时直接使用已经打包好的dll文件,从而减少重复打包的时间。

Webpack 作为一个强大的模块打包器,打包速度一直是开发者关注的热点问题。下面是一些优化打包速度的详细配置:

  1. 使用 HappyPack

HappyPack 可以将 Webpack 的 loader 进行多线程并行处理,从而加快打包速度。可以使用 happypack 插件来配置多线程处理的 loader。

const HappyPack = require('happypack');

module.exports = {
  module: {
    rules: [
      {
        test: /\.js$/,
        use: 'happypack/loader?id=js',
        exclude: /node_modules/
      }
    ],
  },
  plugins: [
    new HappyPack({
      id: 'js',
      threads: 4,
      loaders: ['babel-loader']
    })
  ]
}

其中,id 表示 HappyPack 实例的唯一标识符,threads 表示启动的线程数,loaders 表示要处理的 loader。

  1. 使用 DLLPlugin 进行预编译

DLLPlugin 可以将第三方库先进行打包,然后在开发时直接使用已经打包好的 dll 文件,从而减少重复打包的时间。需要注意的是,在修改了第三方库版本或新增第三方库时,需要重新生成 dll 文件。

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

module.exports = {
  entry: {
    vendors: ['react', 'react-dom', 'lodash']
  },
  output: {
    filename: '[name].dll.js',
    path: path.resolve(__dirname, 'dist'),
    library: '[name]_lib'
  },
  plugins: [
    new webpack.DllPlugin({
      name: '[name]_lib',
      path: path.join(__dirname, 'dist', '[name].manifest.json')
    })
  ]
}
  1. 使用 IgnorePlugin 忽略部分模块

可以使用 IgnorePlugin 忽略掉不需要的模块,在打包时跳过它们,从而提升打包速度。

const webpack = require('webpack');

module.exports = {
  plugins: [
    new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/)
  ]
}
  1. 设置 resolve.alias 配置

resolve.alias 可以将一些常用的模块路径映射为绝对路径,从而缩短 Webpack 查找模块的时间。

module.exports = {
  resolve: {
    alias: {
      '@': path.resolve(__dirname, 'src'),
      'react': path.resolve(__dirname, 'node_modules/react/cjs/react.production.min.js'),
      'react-dom': path.resolve(__dirname, 'node_modules/react-dom/cjs/react-dom.production.min.js')
    }
  }
}

以上是优化 Webpack 打包速度的一些常用配置。当然,在实际项目中,还可以结合其他插件和工具,如 MiniCssExtractPlugin、Webpack Shell Plugin、Autoprefixer 等来进一步优化打包速度。

总之,Webpack如何优化首屏加载时间及流畅度的深度分析,可以针对不同的项目需求进行调整和优化,今后会多多学习,提供经验与感悟与大家一起分享。

转载自:https://juejin.cn/post/7221413753731350587
评论
请登录