哈希css-webpack 性能构建优化

2024-04-10 0 5,536 百度已收录

目录

1:webpack优化配置

webpack4引入了mode模式,可以配置开发和生产模式,并且可以使用一些默认的插件来帮助我们达到想要的效果。

1.1.摇树

这是一种非常有效的减少资源体积的方法,因为最终制作的包中有很多代码不会被使用哈希css,所以可以在打包之前进行处理,将未使用的代码去掉。

前提:不管是自己的还是第三方的,必须是模块化的,而且必须是基于ES6的import导出导出导入方式。 生产模式默认会启动Tree-shaking,主要依赖TerserPlugin插件。

原理:从index.js开始,看看引用了什么,进一步分析所有引入的包或模块中都引用了哪些模块或其他包,最后留下所有需要的东西。

由于Tree-shaking的实现是基于一定的规则的,所以在JS中,可能会涉及到改变全局作用域(窗口对象)。 如果去掉这个抖动,代码中就会出现问题。 这种情况下,需要使用 sideEffects 来告诉 webpack 哪些文件不需要摇动

在 package.json 中配置 sideEffects

"sideEffects": [
  "*.css"
]

注意Babel默认配置的影响

在 babel.config.js 中,presets 会将常用的​​ babel 插件做了一个集合。但是它有一个问题:ES6 模块句型在转码的时候会被转换成其他句型。 我们想要保留 ES6 的模块化句型,因此需要添加 module: false 以便 Tree-shaking 可以工作。

module.exports = {
  presets: [
    [
      '@babel/preset-env',
      {
        modules: false,
        targets: {
          browsers: ['>0.25%'],
        },
        useBuiltIns: 'usage',
        bugfixes: true,
      },
    ],
    '@babel/preset-react',
  ],
  plugins: ['@babel/plugin-proposal-class-properties', '@babel/plugin-transform-runtime'],
}

1.2.JS压缩

简洁的 webpack 插件

支持ES6(Webpack4)的压缩。 terser无论是销量还是功效都比uglifyjs要好。 因此,生产模式下将使用terser作为默认压缩插件。 它的主要作用是减少JS文件的大小。

1.3. 范围改进

/**************** util.js ********************/
export default 'Hello,Webpack';
/**************** index.jsx ******************/
import str from './util';
console.log(str);
/***************** 没有 scope hoisting, webpack 打包后 *******************/
[
  (function (module, __webpack_exports__, __webpack_require__) {
    var __WEBPACK_IMPORTED_MODULE_0__util_js__ = __webpack_require__(1);
    console.log(__WEBPACK_IMPORTED_MODULE_0__util_js__["a"]);
  }),
  (function (module, __webpack_exports__, __webpack_require__) {
    __webpack_exports__["a"] = ('Hello,Webpack');
  })
]
/************************************/
/***************** 有 scope hoisting, webpack 打包后 ********************/
[
  (function (module, __webpack_exports__, __webpack_require__) {
    var util = ('Hello,Webpack');
    console.log(util);
  })
]
/************************************/

如果未启用范围改进,这两个模块将被分为单独的模块。 当其中一个依赖另一个时,就会要求依赖的模块进来,然后调用需要的模块; 范围改进启用后,会做合并分析,当发现有这些依赖的调用时,会尝试将依赖合并到调用中,最终会变得更加精简。

1.4.Babel优化配置

1. 必要时引用polyfill

Polyfill是为了兼容老的浏览器来实现新的功能或者新的规范。因为这个比较大,我们需要把涉及到的东西都介绍一遍,但是我们可能会用到其中较小的一部分。 这种情况下,我们需要在 babel.config.js 中配置 useBuiltIns: 'usage' 。

2、按需引入辅助功能

如需复用 babel 转码后的辅助功能,请在 babel.config.js 中配置 @babel/plugin-transform-runtime 插件

3.根据目标浏览器按需转换代码

在preset-env中配置target: { browsers: ['>0.25%'], },即支持市场份额超过0.25%的浏览器

2:webpack的依赖优化

使用webpack打包之后,你会得到一定的优化,但是你也可以在webpack打包过程中进行一定的优化。

2.1.noParse(不解析)

module: {
  noParse: /lodash/, // loadsh比较独立
  noParse: /^(vue|vue-router|vuex|vuex-router-sync)$/, // vue-cli里的配置
}

2.2.Dll插件

将我们复用的库提取出来,变成引用方法,这样我们就不用每次都重新构建库,这样可以大大加快创建过程。

/* package.json */
{
  "scripts": {
    "dll-build": "cross-env NODE_ENV=production webpack --config webpack.dll.config.js"
  }
}
/* webpack.dll.config.js */
const path = require('path')
const webpack = require('webpack')
module.exports = {
  mode: 'production',
  entry: {
    react: ['react', 'react-dom'],
  },
  output: {
    filename: '[name].dll.js',
    path: path.resolve(__dirname, 'dll'),
    library: '[name]',
  },
  plugins: [
    new webpack.DllPlugin({
      name: '[name]',
      path: path.resolve(__dirname, 'dll/[name].manifest.json'),
    }),
  ],
}
/* webpack.config.js */
const DllReferencePlugin = require('webpack/lib/DllReferencePlugin');
module.exports = smp.wrap({
  plugins: [
    /* 动态链接库引用 */
    new DllReferencePlugin({
      manifest: require(`${__dirname}/dll/react.manifest.json`),
    }),
  ],
}

三:Webpack细节优化

代码分割

Webpack代码拆分方法:

1.提取我们代码中重用的东西

2.将我们的业务逻辑与第三方依赖分离

webpack处理文件路径时,在Unix系统中仍然包含/,在Windows系统中仍然包含,所以要在其中添加[\/]。

chunks:有效值为all、async、initial,initial是同步加载,async是异步加载

minChunks:拆分模块之前必须共享的最小块数

module.exports = smp.wrap({
  optimization: {
    splitChunks: {
      cacheGroups: {
        vendor: {
          name: 'vendor',
          test: /[\/]node_modules[\/]/,
          minSize: 0,
          minChunks: 1,
          priority: 10,
          chunks: 'initial',
        },
        common: {
          name: 'common',
          test: /[\/]src[\/]/,
          chunks: 'all',
          minSize: 0,
          minChunks: 2,
        },
      },
    },
  },
})

<Suspense fallback={
Loading...
}>

四:Webpack资源压缩

webpack4模式

4.1.Terser压缩JS

模式:'生产'行代码相当于下面编写的所有代码

// webpack.production.config.js
module.exports = {
  mode: 'production',
  performance: {
    hints: 'warning',
  },
  output: {
    pathinfo: false,
  },
  optimization: {
    namedModules: false,
    namedChunks: false,
    nodeEnv: 'production',
    flagIncludedChunks: true,
    occurrenceOrder: true,
    sideEffects: true,
    usedExports: true,
    concatenateModules: true,
    splitChunks: {
      hidePathInfo: true,
      minSize: 30000,
      maxAsyncRequests: 5,
      maxInitialRequests: 3,
    },
    noEmitOnErrors: true,
    checkWasmTypes: true,
    minimize: true,
  },
  plugins: [
    new TerserPlugin(/* ... */),
    new webpack.DefinePlugin({ 'process.env.NODE_ENV': JSON.stringify('production') }),
    new webpack.optimize.ModuleConcatenationPlugin(),
    new webpack.NoEmitOnErrorsPlugin(),
  ],
}

4.2.mini-css-extract-plugin 压缩CSS

module.exports = {
  plugins: [
    new MiniCssExtractPlugin({
      filename: '[name].[hash].css',
      chunkFilename: '[id].[chunkhash:8].css',
    }),
    new OptimizeCssAssetsPlugin({
      cssProcessorPluginOptions: {
        preset: ['default', { discardComments: { removeAll: true } }],
      },
      canPrint: true,
    }),
  ]
}

4.3.HtmlWebpackPlugin-minify 压缩 HTML

{
  collapseWhitespace: true, // 移除空格、换行符
  keepClosingSlash: true, // 保留元素的末尾斜杠
  removeComments: true, // 移除注释
  removeRedundantAttributes: true, // 移除冗余属性(默认值)
  removeScriptTypeAttributes: true, // 移除script标签中的type属性
  removeStyleLinkTypeAttributes: true, // 移除style标签中的type属性
  useShortDoctype: true // 使用html5短的描述方式
}

五:基于webpack的资源持久化缓存

哈希的特点:离散唯一值。 如果内容不变,计算值也不变。

contenthash:能够区分同一资源的CSS和JS文件的哈希值。 将根据内容生成哈希值。 当仅更改 JS 时,CSS 重新打包后会保持原来的 hash 值。部署更新时,可以充分利用浏览器缓存,保证用户体验和更新平滑过渡。

module.exports = {
  output: {
    path: `${__dirname}/build`,
    filename: '[name].[hash].bundle.js',
    chunkFilename: '[name].[chunkhash:8].bundle.js',
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: '[name].[contenthash].css',
      chunkFilename: '[id].[contenthash:8].css',
    }),
  ]
}

六:基于webpack的应用程序规模测量与分析

常用工具:

Webpack 图表

通过:webpack --profile --json > stats.json 生成stats.json 文件,然后将此文件上传到本网站。

这个可能还不够详细。 如果你想进一步分析,可以使用bundle-analyzer工具。 这里我们使用source-map-explorer来进一步分析。

npm i source-map-explorer

此分析不是基于我们的捆绑文件,而是基于源映射。 需要生成源映射。

/* package.json */
{
  "scripts": {
    "analyze": "source-map-explorer 'build/*.js'"
  },
}
/* webpack.config.js */
module.exports = smp.wrap({
  mode: 'production',
  devtool: 'source-map'
}

官方推荐的bundle-analyzer可以得到可视化的图表,但与source-map-explorer相比,只能给出大概的视图,缺少一些具体的内容(大小)。

速度分析可以使用speed-measure-webpack-plugin。 运行 npm run build 以查看所有插件和所有加载器的使用情况。

const SpeedMeasurePlugin = require('speed-measure-webpack-plugin')
const smp = new SpeedMeasurePlugin()
module.exports = smp.wrap({...})

七:React按需加载的实现方法

代码分割最初是为了解决请求过大的问题。 通过请求哈希css,将整个包加载到主页。 此时网络开销比较小,包体积较大,所以下载时间较长; 我们可以将较大的包拆成几个大包,而小包只能在调用时才会被加载(按需加载)。如果将拆分级别定义为组件,那么所有组件都会被拆分为一个独立的模块,并且会有很多束或块。 那么就需要发起多个请求,开销会更大。

通常最合理的做法是基于路由来做按需加载。只有当我们页面上的某些组件在不同路由的页面上复用时,我们才会将组件单独拆解。

import loadable from '@loadable/component'
// 使用React-Loadable动态加载组件
const LoadableAbout = loadable(() => import('./About.jsx'), {
  fallback: '
loading...
', }) class App extends React.Component { render() { return ( ) } }

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

悟空资源网 css 哈希css-webpack 性能构建优化 https://www.wkzy.net/game/200468.html

常见问题

相关文章

官方客服团队

为您解决烦忧 - 24小时在线 专业服务