webpack学习总结

本文详细总结了webpack的使用,包括devtool配置sourceMap的选项,loader的原理及常见类型如file-loader和babel-loader,plugin的作用及常用插件如html-webpack-plugin。深入探讨了tree shaking的实现原理,并介绍了code splitting的概念。此外,还涵盖了webpack的多页面打包、热更新机制、项目体积优化和打包速度提升策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

devtool配置sourceMap

  • inline 不生成单独的sourceMap文件,而是直接打包进js文件里

  • module 映射第三方和loader的代码

  • cheap 只映射到出错行,不精确到列;只映射业务代码

  • eval 速度最快,但不全面

  • development: 建议cheap-module-eval-source-map

  • production: 默认不加最好,需要调试建议cheap-module-source-map

loader是什么

webpack只能理解JavaScript和JSON文件。loader让webpack能够去处理其他类型的文件,并将它们转换为有效模块,以供应用程序使用,以及被添加到依赖图中。

常见loader

  • file-loader: 将图片等文件打包进去
  • url-loader: 将图片等文件打包进去,如果文件小于字节限制,返回DataURL
rules: [
  {
    test: /\.(png|jpg|gif)$/i,
    use: [
      {
        loader: 'url-loader',
        options: {
          limit: 8192
        }
      }
    ]
  }
]
  • style-loader css-loader postcss-loader less-loader:
    执行顺序从右到左
rules: [
  {
    test: /\.css$/,
    use: ['style-loader', 'css-loader','postcss-loader','less-loader'],
  },
]
  • babel-loader:
    将es6的新语法转换成es5代码,而不转换api。例如const、let、箭头函数会转换,但是Promise、Generator、Set、Proxy、Symbol等全局变量不会转换,可在main.js使用import @babel/polyfill在全局添加原生方法解决。
// 业务代码中
rules: [
  {
    test: /\.js$/,
    exclude: /node_modules/,//不转化node_modules外部依赖,加快打包速度
    use: {
       loader: "babel-loader",
       options: {
         presets: [
           [
             "@babel/preset-env",
             {
               targets: {
                 chrome: "67",// 超过此版本无需再转换
                 ie: "11"
               },
               useBuiltIns: "usage" //polyfill仅添加用到的全局api(按需引入)
             }
           ]
         ]
       },
    }
  }
]
// polyfill会造成全局变量污染,所以开发类库的时候,换一种闭包导入形式的写法
rules: [
  {
    test: /\.js$/,
    exclude: /node_modules/,//不转化node_modules外部依赖,加快打包速度
    use: {
       loader: "babel-loader",
       options: {
         "plugins": [
             [
               "@babel/plugin-transform-runtime",
               {
                 "corejs": 2, // 需要安装 @babel/runtime-corejs2 仅支持全局变量如Promise和静态属性如Array.from
                 "helpers": true,
                 "regenerator": true,
                 "useESModules": false,
               }
             ]
           ]
       },
    }
  }
]

编写一个loader

//replaceLoader
const loaderUtils = require('loader-utils')
module.exports = function(source){
  const options = loaderUtils.getOptions(this);
  return source.replace('name',options.name);
}
//webpack.config.js
rules: [
  {
    test: /\.js$/,
    use: [
      {
        loader: path.resolve(__dirname,'./loaders/replaceLoader.js'),
        options: {
          name: 'you name'
        }
      }
    ]
  }
]

plugin是什么

主要的作用是根据webpack提供的一些hooks钩子函数来进行一些额外的操作。

常见plugin

  • html-webpack-plugin 在打包结束后自动生成一个html文件,并把生成的js文件引入
plugins: [new HtmlWebpackPlugin({
  template:'src/index.html'
})]
  • clean-webpack-plugin 在打包之前清理文件夹
plugins: [new CleanWebpackPlugin(['dist'])]
  • ProvidePlugin
    shimming垫片
const webpack = require('webpack')
plugins:[
  new webpack.ProvidePlugin({
    $:'jquery', //如果某js用到了$, 则自动在该js头部引入jq
    _:'lodash'
  })
]

编写一个plugin

class CopyrightWebpackPlugin{
  apply(compiler){
    compiler.hooks.emit.tapAsync('CopyrightWebpackPlugin',(compilation,cb)=>{
      compilation.assets['copyright.txt']={
        source:function(){return '123456789'},
        size:function(){return 9}
      }
      cb();
    });
  }
}
module.exports = CopyrightWebpackPlugin

tree shaking 是什么?原理?

  • tree shaking必须遵循ES6的模块规范(import & export),如果是CommonJS规范(require)则无法使用。
  • webpack对代码进行标记,把import & export标记为3类:
    1. 所有import标记为 /* harmony import */
    2. 被使用过的export标记为 /* harmony export ([type]) */,其中 [type] 和webpack内部有关,可能是 binding, immutable 等等。
    3. 没被使用过的import标记为 /* unused harmony export [FuncName] */,其中 [FuncName] 为 export 的方法名称
  • 之后在Uglifyjs(或者其他类似的工具)步骤进行代码精简,把没用的都删除。

code splitting 是什么?原理?

webpack多页面打包配置

  • entry里面key-页面名称,value-js文件地址
  • plugins里面为每个入口文件new HtmlWebpackPlugin()
const HtmlWebpackPlugin = require("HtmlWebpackPlugin");
const glob = require("glob");

const htmlPluginArray = [];
const entry = {};

glob.sync('./src/pages/*/index.js').forEach(function (filePath) {
  let name = filePath.match(/\/pages\/(.+)\/index.js/);
  name = name[1];
  entry[name] = filePath;
  htmlPluginArray.push(new HtmlWebpackPlugin({
    filename: `./${name}/index.html`,
    template: './src/index.html',
    chunk: ['vendors','chunk',name],
  }))
});

module.exports={
  entry:entry,
  plugins:[...htmlPluginArray],
  output: {
    publicPath: 'http://cdn.com',
    filename: '[name].[contenthash].js',
    chunkFilename: '[name]_[contenthash].js',
    path: 'dist dir',
  },
}

webpack 的热更新是如何做到的?说明其原理?

webpack如何优化项目体积

如何提升webpack的打包速度

  • 更新webpack\node\npm版本
  • 在尽可能少的模块上应用loader
    例如babel-loader exclude
rules: [
  {
    test: /\.js$/,
    exclude: /node_modules/,//不转化node_modules外部依赖,加快打包速度
    use: {
       loader: "babel-loader",
    }
  }
]
  • Plugin尽可能少并确保可靠
  • 使用DllPlugin提升webpack打包速度
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值