Skip to content
本页目录

Webpack

高级配置

  1. 如何配置多入口?

分别配置entrychunksoutputplugins,具体如下:

JavaScript
module.exports = {
  entry: {
    index: path.join(srcPath, 'index.js'),
    other: path.join(srcPath, 'other.js')
  },
  ouput: {
    // filename: 'bundle.[contentHash:8].js',
    filename: '[name].[contentHash:8].js' // name 即多入口chunk
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: path.join(srcPath, 'index.html'),
      filename: 'index.html',
      // 页面引用哪些js文件(代码分割)
      chunks: ['index'] // 只引用 index.js
    }),
    new HtmlWebpackPlugin({
      template: path.join(srcPath, 'other.html'),
      filename: 'other.html',
      chunks: ['other']
    })
  ]
}
  1. 如何抽离压缩CSS文件?

分别配置module.rulespluginsoptimization,具体如下:

JavaScript
module.exports = {
  // 生产环境
  mode: 'production',
  module: {
    rules: [
      {
        test: /\.css$/,
        loader: [
          // 'style-loader', // 开发环境
          MiniCssExtractPlugin.loader,
          'css-loader',
          'postcss-loader'
        ]
      }
    ]
  },
  plugins: [
    // 抽离CSS文件
    new MiniCssExtractPlugin({
      filename: 'css/main.[contentHash:8].css'
    })
  ],
  optimization: {
    // 压缩CSS文件
    minimizer: [new TerserJSPlugin({}), new OptimizeCSSAssetsPlugin({})]
  }
}
  1. 如何抽离公共代码和第三方代码?

通过配置optimization.splitChunksplugins里的chunks,具体如下:

JavaScript
module.exports = {
  optimization: {
    // 分割代码
    splitChunks: {
      // initial 入口chunk,不处理异步文件;async  异步chunk,只处理异步文件
      chunks: 'all',
      // 缓存分组
      cacheGroups: {
        // 第三方模块
        vender: {
          name: 'vender', // chunk名称
          priority: 1, // 权限高的优先抽离,解决与其它模块冲突
          test: /node_modules/,
          minSize: 0, // 最小限制
          minChunks: 1 // 最少复复用次数
        },
        // 公共模块
        common: {
          name: 'common',
          priority: 0,
          minSize: 0,
          minChunks: 2
        }
      }
    }
  }
}
  1. 如何实现异步加载(懒加载)?

使用import()函数(引入动态数据)

  1. 如何处理JSXVue

使用babel(配置.babelrc文件),在module.rules里分别配置babel-loadervue-loader

性能优化

  1. 如何优化(开发环境)打包构建速度?
  • 优化babel-loader ==> 使用缓存cacheDirectory;使用includeexclude
  • 使用IgnorePlugin插件避免引入无用模块,像moment库的语言库只用中文时,直接手动导入中文库;
  • 使用noParse配置规则避免重复打包;
  • 配置happyPack多进程打包(大项目)
  • 使用ParalleUglifyPlugin多进程代码压缩(大项目)
  • 热更新
  • 使用DllPlugin将第三方库预先打包成单独的文件,减少构建时间
  1. 如何优化产出代码?
  • 小图片使用BASE64编码;
  • bundlehash
  • 使用splitChunk提取公共代码;
  • 使用IgnorePlugin
  • ouput静态资源配置CDN加速;
  • 开启Scope Hosting:代码体积更小,创建更少的作用域,更好的代码可读性

机制原理

  1. 热更新HMR(即webpack-dev-server,以下简称WDS)实现原理?

HMR即在浏览器不刷新的情况下,用新变更的模块替换掉旧的模块。
实现原理:通过WDS和浏览器之间维护了一个WebSocket服务。当本地资源发生变化后,webpack会先将打包生成新的模块代码放入内存中,然后WDS向浏览器推送更新,并附带上构建时的hash,让客户端和上一次资源进行对比,客户端对比出差异后会向WDS发起Ajax请求获取到更改后的内容,通过这些信息再向WDS发起jsonp请求获取到最新的模块代码,最后HotModulePlugin将会对新旧模块进行对比,在更新模块的同时更新模块间的依赖引用。

  1. Proxy工作原理?
null

利用http-proxy-middleware这个http代理中间件,实现请求转发给其他服务器。
==> 当本地浏览器Local向服务器Server发起请求时,由于浏览器的同源策略,存在跨域问题,Server的响应会被浏览器拦截;
==>而代理服务器Proxy与服务器Server之间请求数据并不会存在跨域行为,代理服务器Proxy传递数据给本地浏览器Local的过程中,两者同源,也不存在跨域行为。

  1. tree-shaking工作原理?

基于ES Module的静态引入规则,在编译的时候可正确判断到底加载了那些模块,进而删除无用代码。
CommonJSES Module区别?

区别CJSESM
导入可写在判断中只能写在模块顶层
导出单个值可以多个值
输出值的拷贝值的引用
时机运行时加载编译时输出
this当前模块undefined
  1. LoaderPlugin实现原理?

参考文章LoaderPlugin实现原理
LoaderPlugin的区别?

配置上:

  • Loadermodule.rules下配置:值类型为数组,每⼀项都是⼀个Object,⾥⾯描述了对于什么类型的⽂件(test),使⽤什么加载(loader)和使⽤的参数( options);
  • Pluginplugins下配置:值类型也为数组,每一项是一个Plugin的实例,参数都通过构造函数传入。

功能上:

  • Loader本质上是一个函数,由于webpack只能解析原生JavaScipt文件,所以对于其它类型的文件就需要一个转换器,将其转换为原生JavaScipt文件;
  • Plugin是一个插件,用于增强webpack功能。
  1. webpack的构建流程?
null
  1. 初始化:启动构建,读取与合并配置参数,加载Plugin,使用配置参数实例化Compiler
  2. 编译:从Entry出发,针对每个Module串行调用对应的Loader去翻译文件的内容,再找到该Module依赖的 文件内容,递归地进行编译处理;
  3. 输出:将编译后的Module组合成Chunk,将Chunk转换成Bundle文件,输出到文件系统中。

modulechunkbundle的区别?

module:各源码文件,在编译的时候会从entry中递归寻找出所有依赖的模块;
chunk:多模块的合成,用于代码的合并和分割,在构建过程中一起被打包到一个文件中;
bundle:最终输出文件