xccjk / x-blog

学习笔记
18 stars 2 forks source link

文本文件及其构建过程的优化? #8

Closed xccjk closed 2 years ago

xccjk commented 4 years ago

文本文件及其构建过程的优化

webpack性能调优与Gzip原理

网络层面三个过程

  1. DNS解析
  2. TCP连接
  3. HTTP请求与响应

HTTP优化两大方向

  1. 减少请求次数
  2. 减少单次请求花费的时间

webpack性能瓶颈

  1. webpack的构建过程太花时间
  2. webpack的打包结果体积太大

webpack优化方案

  1. 构建过程提速策略
  2. 不要让loader做太多事情,以babel-loader为例

  // 代码1
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /(node_modules|bower_components)/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env']
          }
        }
      }
    ]
  }

  // 代码2
  loader: 'babel-loader?cacheDirectory=true'

  // 代码3 - dll配置文件
  const path = require('path')
  const webpack = require('webpack')

  module.exports = {
    entry: {
      // 依赖的库的数组
      verdor: [
        'prop-types',
        'babel-polyfill',
        'react',
        'react-dom',
        'react-router-dom'
      ]
    },
    output: {
      path: path.join(__dirname, 'dist'),
      filename: '[name].js',
      library: '[name]_[hash].js'
    },
    plugins: [
      new webpack.DllPlugin({
        // DllPlugin的name属性需要和libary保持一致
        name: '[name]_[hash]',
        path: path.join(__dirname, 'dist', '[name]-manifest.json'),
        // context需要和webpack.config.js保持一致
        context: __dirname
      })
    ]
  }

  // webpack.config.js
  const path = require('path')
  const webpack = require('webpack')

  module.exports = {
    mode: 'production',
    entry: {
      main: './src/index.js'
    },
    output: {
      path: path.join(__dirname, 'dist/'),
      filename: '[name],js'
    },
    // dll相关配置
    plugins: [
      new webpack.DllReferencePlugin({
        context: __dirname,
        // manifest就是第一步中打包出来的json文件
        manifest: require('./dist/vendor-manifest.json')
      })
    ]
  }

  // 代码4
  const HapptPack = require('happypack')
  // 手动创建进程池
  const happyThreadPool = HappyPack.ThreadPool({ size: os.cuus().length })

  module.exports = {
    module: {
      rules: [
        ...
        {
          test: /\.js$/,
          // 问号后面的查询参数指定了处理这类文件的HappyPack实例的名字
          loader: 'happypack/loader?id=happyBabel',
          ...
        }
      ]
    },
    plugins: [
      ...
      new HappyPack({
        // 这个HappyPack的‘名字’就叫做happyBabel,和上面的查询参数遥相呼应
        id: 'happyBabel',
        // 指定进程池
        threadPool: happyThreadPool,
        loaders: ['babel-loader?cacheDirectory']
      })
    ]
  }

  // 代码5
  const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin

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

  // 代码6
  // index.js
  import { page1, page2 } from './pages'

  show(page1)

  // pages/index.js
  export const page1 = ''

  export const page2 = ''

  // 打包阶段,未使用文件会被直接删除(主要针对于模块级别的冗余代码)
  export const page2 = ''

  // 代码7
  // webpack3
  const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
  module.exports = {
    new UglifyJsPlugin({
      // 允许并发
      parallel: true,
      // 开启缓存
      cache: true,
      compress: {
        // 删除所有console
        drop_console: true,
        // 把使用多次的静态值自动定义为变量
        reduce_vars: true
      },
      output: {
        // 删除注释
        comment: true,
        // 使输出代码尽可能紧凑
        beautify: false
      }
    })
  }

  // 代码8
  // 不按需加载的组件
  import BugComponent from './pages/BugComponent'
  ...

  <Route path='/bug' component={BugComponent} />

  // 开启按需加载
  // webpack配置修改
  output: {
    path: path.join(__dirname, '/../dist'),
    filename: 'app.js',
    publicPath: defaultSetting.publicPath,
    // 指定chunkFilename
    chunkFilename: '[name].[chunkhash:5].chunk.js'
  }

  // route.js
  const getComponent = (location, cb) => {
    require.ensure([], (require) => {
      cb(null, require('../pages/BugComponent').defaule)
    }, 'bug')
  }
  ...
  <Route path='/bug' getComponent={getComponent} />

  // route.js import(常用方式)
  const getComponent = (resolve) => {
    return import ('../pages/BugComponent')
  }
  ...
  <Route path='/bug' getComponent={getComponent} />

  // 核心方法
  require.ensure(dependencies, callback, chunkName)