webpack学习笔记

webpack作用:处理代码压缩混淆、浏览器端js的兼容性以及性能优化

webpack在项目中安装过程

1、

npm i webpack webpack-cli -g //全局安装webpack(必须)

npm i webpack@5.42.1 webpack-cli@4.7.2 -D //局部安装 Webpack 到项目(必须)

2、

webpack.config.js 配置

/* 
webpack.config.js:指示webpack干哪些活(当你运行webpack指令时,会加载这里面的内容)
        注:所有构建工具都是基于node.js平台运行的 模块化采用commonjs
 */
const { resolve } = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin"); //新建模板骨架插件
const MiniCssExtractPlugin = require("mini-css-extract-plugin"); //引入从js中提取css的插件
const WorkboxWebpackPlugin=require("workbox-webpack-plugin");
const OptimizeCssAssetsWebpackPlugin = require("optimize-css-assets-webpack-plugin"); //压缩css插件
​
//如果browserslist要开发模式则需要设置nodejs的环境变量
process.env.NODE_ENV = "development";
​
/* 
缓存:
  babel缓存:
    设置 cacheDirectory:true,   作用:开启缓存机制。让第二次打包速度更快
  文件资源缓存:
    hash每次webpack构建都会生成唯一的hash值
      问题:因为css和js用的是同一个hash值,如果重新打包则会导致所有缓存失效
            但我可能只改动了一个文件
      解决:Chunkhash 根据打包入口生成的hash值。入口一样chunk一样
      问题:css和js还是同一个hash值 因为css是在js中被引入的 所有同属一个chunk
      最终解决:使用contenthash:根据文件内容生成hash值,文件内容不一样hash值一定不一样(不考虑哈希碰撞)
      作用:让代码上线运行缓存更好使用
*/
​
​
/* 
tree shaking(树摇 把没有用的叶子摇下去): 去除在应用程序中没有应用到的代码,使代码体积更小
前提:1、必须使用es6模块化  2、开启production环境
​
  在package.json中配置 "sideEffects":false 即所有代码没有副作用都可以进行"树摇" 可能会误摇css或者js文件
  例:不要摇css文件 则在package.json中配置 "sideEffects":["*.css"]
*/
​
/* 
PWA(离线访问技术):workbox-webpack-plugin
​
*/
/* 复用css */
const commonCssLoader = [
  //在页面中创建style标签,将js中的'样式字符串'插入标签并添加到head生效
  // "style-loader",
  /*
  取代style-loader 提取js中的css单独成文件  同时html自动引入
  将CSS文件变成commonjs模块加载到js中,里面内容是样式字符串 
  */
  MiniCssExtractPlugin.loader,
  "css-loader",
​
  /* 
  解决CSS兼容性问题:postcss-loader --> postcss-preset-env 
  帮postcss找到package-json中的browserslist里面的配置,通过配置加载指定的兼容性
  */
​
  //修改配置要以对象的方式     browserslist默认是生产模式 与mode无关
​
  {
    loader: "postcss-loader",
    options: {
      ident: "postcss",
      plugins: () => [
        //postcss的插件
        require("postcss-preset-env")(),
      ],
    },
  },
],;
​
​
​
module.export = {
  entry: "./src/index.js",    //单页面  单入口
/* 
  entry: {
    index:"./src/index.js",
    text:"./src/text.js"          //多页面  多入口  一个入口生成一个bundle.js文件  kv形式
  },
*/
  output: {
    //[name]取文件名  多入口的情况下使用    1强2
    filename: "js/[name].[Contenthash:10].js", //输出文件名
    path: resolve(__dirname, "build"), //_dirname是当前文件的目录绝对路径(即Webpack)
  },
  //loader的配置
  //不同文件要配置不同的loader处理
  module: {
    rules: [
      {
        /* 对js进行语法检查 eslint-loader eslint 
          注:只检查自己写的源代码,第三方的库不用检查
          检查规则在package.json中eslintConfig中设置
          "eslintConfig":{
            "extends":"airbnb-base"     继承下载的airbnb-base库中的规则
          }
​
          airbnb规则需要三个插件 eslint-config-airbnb-base、eslint、eslint-plugin-import
        */
        test: /\.js$/,
        exclude: /node_modules/, //排除检查第三方库是否错误
        loader: "eslint-loader",
        enforce:'pre',     //一般情况下一个文件一个loader执行 enforce设置为pre表示该loader优先执行
        options: {
          //自动修复js中的语法错误
          fix: true,
        },
      },
      /* 
      oneOf中只能使用一个loader处理一种类型的文件,不能两个配置处理同一类的文件。如果需要两个则提取到oneOf以外
      防止一个文件反复的被多个loader执行。优化生产环境的打包速度
      */
    ],
      oneOf:[
        {
          //匹配以CSS为后缀的文件
          test: /\.css$/,
          //use数组中loader的执行顺序:右到左,下到上
          use: [
            ...commonCssLoader
          ],
        },
        {
          test: /\.less$/,
          //使用多个loader用use
          use: [
             ...commonCssLoader,          //...commonCssLoader为展开commonCssLoader
            "less-loader", //less-loader将less文件转换为css文件
          ],
        },
  
        {
          test: /\.(png|jpg|gif)$/,
          loader: "url-loader", //处理样式文件中的img图片
          //使用一个loader要下载file-loader,通常用use
          options: {
            //图片size小于8kb,就会被base64处理
            //base处理的优点是减少请求数量降低服务器压力 缺点是图片体积变大图片请求速度会变慢
            limit: 8 * 1024,
            /* 
            由于url-loader默认采用es6解析,而html-loader引入图片是commonjs,解析时候会冲突
            所有关闭url-loader的es6解析,采用commonjs解析
            */
            esModule: false,
            //图片名字过长 使用name重命名
            name: "[hash:10].[ext]",
            outputPath: "imgs",
          },
        },
        {
          test: /\.html$/, //处理HTML中的img图片
          loader: "html-loader",
          outputPath: "imgs",
        },
        {
          //打包其他资源  排除常用资源就是其他资源
          exclude: /\.(html|css|js)$/,
          loader: "file-loader",
          options: {
            limit: 8 * 1024,
            esModule: false,
            name: "[hash:10].[ext]",
          },
          outputPath: "media",
        },
        {
          /*
          js兼容性处理: 
          babel-loader  @babel/core
           1.@babel/preset-env 能够解决简单的js语法 es6如promise就不能解决兼容  在options中的presets预设
          2.@babel/polyfill    直接在所需的js文件中import '@babel/polyfill'即可  但文件体积大了
          3.core-js   按需分配(最佳方案1+3) 使用第三种就不能使用第二种
          */
          text: /\.js$/,
          exclude: /node_modules/, //排除检查第三方库
          loader: ":babel-loader",
          options: {
            //presets(预设):指示babel做怎么样js兼容
            presets: [
              "@babel/preset-env",
              //按需分配
              {
                useBuiltIns: "usage",
                //指定core-js版本
                corejs: {
                  version: "3",
                },
                //指定兼容性做到哪个版本浏览器
                target: {
                  chrome: "60",
                  firefox: "60",
                  ie: "9",
                  safari: "10",
                },
              },
            ],
            //开启babel缓存,第二次构建会优先读取缓存,提升速度
            cacheDirectory:true,
          },
        },
​
      ]
  },
  //plugins比loader多一步引入
  plugins: [
    new HtmlWebpackPlugin({
      option:{
        title:'我是网页title'
      },
      template: "./src/index.html", //创建一个HTML,模板为index.html 并引入打包输出的所有资源
      minify: {
        //压缩html代码
        //移除空格
        collapseWhitespace: true,
        //移除注释
        removeComments: true,
      },
    }),
    new MiniCssExtractPlugin({
      //对打包的css重命名
      filename: "/css/main.[Contenthash:10].css",
    }),
    new OptimizeCssAssetsWebpackPlugin(), //压缩css文件
​
    new WorkboxWebpackPlugin.GenerateSW({
      /* 1、帮助serviceworker快速启动
        2、删除旧的serviceworker
        生成一个 serviceworker配置文件    
      */       
      clientsClaim:true,      
      skipWaiting:true
    })
  ],
  /*
  针对js文件
   单入口 将node_module中的代码单独打包成一个chunk+入口chunk输出         实现并行加载提高运行速度
   多入口 自动分析多入口chunk中,有没有公共的文件。如果有会打包成单独一个chunk
    optimization在生产环境中才有意义  除了chunk:'all' 其他均为默认配置
   */
  optimization:{
    splitChunks:{
      chunk:'all',
      miniSize:'30*1024',    //大于最小才会分割
      maxSize:'0',        //不限制大小
      miniChunk:'1',      //要提取的提取的chunk至少被引用一次
      maxAsyncRequests:'5',  //按需加载时 最大并行加载数量为5
      maxInitialRequests:'3',   //入口js最大并行为3
      autoMaticNameDelimiter:'~',  //名称连接符为~
      name:true,           //可以使用命名规则
      cacheGroups:{
        //分割chunk的组
          /* 
          >............<省略配置
          */
      }
    },
    runtimeChunk:{
      //当前模块记录其他模块的hash单独打包成一个文件runtime 解决由于a文件改动导致b文件的contentchash改变
      name:entrypoint=>`runtime-${entrypoint.name}`
    }
  },
  mode: "development",
  resolve:{
    alias:{
      $css:resolve(__dirname,'src/css'),   //设置路径别名为$css 优化简写路径
    },
    extensions:['.js','.json','css'],    //配置省略文件路径的后缀名 省略什么加什么
    modules:[resolve(__dirname,'../Webpack/node_modules'),'node_modules'],           //指定webpack解析模块的目录
  },
  externals:"jquery",      //最终的bundle不打包jquery
​
  /* 
  开发服务器devServer:自动化编译,打开浏览器,刷新浏览器
  特点:只会在内存中编译打包,不会有输出
  启动devServer指令为:npx webpack-dev-server(因为是下载在本地 所以要用npx启动dev-server服务器)
  正常打包指令为:webpack  --mode=development
          注:修改了webpack配置要重启服务才会生效
  */
  devServer: {
    //构建后的目录路径
    contentBase: resolve(__dirname, "build"),
    //监视构建的目录,一旦文件发生变化自动reload
    watchContentBase:true,
    //忽略文件变化选项
    watchOptions:{
      ignored:/node_module/,
    },
    //启动gzip压缩 让代码运行速度更快
    compress: true,
    //开发服务器的端口号
    port: 5000,
    //自动打开默认浏览器
    open: true,
    // HMR:热模块替换  作用:当一个模块发生变化,只会重新打包这一个模块,而不是打包所有。提升构建速度
    hot:true,
    //关闭服务器启动日志
    clientLogLevel:'none',    
    //除了基本启动信息,其他信息都不要显示   一般和clientLogLevel:'none'联用
    quiet:true,
    //如果发生错误,不要全屏提示
    overlay:false, 
    //服务器代理(解决跨域问题),一旦devsevery接收到./api开头的请求转发到'http://localhost:3000'服务器上处理
    proxy:{
      './api':{
        target:'http://localhost:3000',
        pathRewrite:{
          '^/api':'',    //重写路径 转发的时候去掉api
        }
      }      
    }              
  },
​
  devtool:'source-map'   //优化调试
  /* 
  内联和外部的区别是:外部

3、在package-json的script节点下新增dev和bulid命令用来打包

  

  "scripts": {
    "dev": "webpack serve",
    "build": "webpack --mode production"
  },

4、根据入口文件输出打包文件,然后所需的地方导入打包文件<script src="/budle.js"></script>就可以认webpack帮我们处理兼容性问题,打包文件放在内存中修改比较快

webpack中的默认约定

1、默认打包入口为src->index.js

2、默认的输出文件路径dist->main.js

查看webpack和webpack-cli版本

node_modules/.bin/webpack -v

node_modules/.bin/webpack-cli -v

webpack的各个插件

#安装dev-Server 一修改源代码就自动打包 无需手动打包 但页面不会实时刷新

npm i webpack-dev-server -D

#打包html插件(需要require引入)

npm i html-webpack-plugin -D

#html压缩

在HtmlWebpackPlugin中的minify设置

webpack遇见非.js的文件要对应的loader插件解析

#样式的loader插件 采用base64格式的图片可以防止多余的图片加载请求 但是图片大小会变大

#打包脚本中的图片资源

npm i style-loader css-loader less-loader -D

#打包样式中图片资源

npm i file-loader url-loader -D

#打包骨架中的图片

npm i html-loader -D

#自动清除dist目录的旧文件(插件需引入)

npm i clean-webpack-plugin -D

#从js中提取css(插件需引入)

npm i mini-css-extract-plugin -D

#压缩css(插件需引入)

npm i optimize-css-assets-webpack-plugin -D

#css兼容性问题

npm i postcss-loader postcss-preset-env -D 同时在packjson中进行browserslist配置

#js语法规范检查

npm i eslint-loader eslint-config-airbnb-base、eslint、eslint-plugin-import -D 同时在packjson中进行eslintConfig配置

#js兼容性问题

npm i babel-loader @babel/core @babel/plugin-proposal-decorators -D

第三种插件可替换方案

(@babel/preset-env 解决基本的js兼容问题) (@babel/polyfill 解决全部es6语法的兼容性问题) (core-js 解决所需的js兼容性问题 )

#js压缩

生产模式下会自动压缩js代码

#多进程打包(一般为js)

npm i thread-loader -D

#将某个资源打包输出,并在html中引入该资源

npm i add-asset-html-webpack=plugin -D

webpack优化

1、开发环境性能优化

(1)优化打包构建速度 :HMR热模块替换 //如果只有一个模块发生变化就只会重新构建该模块,其他模块使用之前的缓存 (2)优化代码调试:devtool:'eval-source-map' /(存储着压缩混淆后的代码所对应的转换前的位置(行号),可 看见源码) 开发环境用

devtool:'nosources-source-map' //可见位置不可见源码 生产环境用

2、生产环境性能优化

(1)优化打包速度:

一、oneOf 二、babel缓存 //缓存运行结果,第二次打开速度更快 三、多进程打包 四、externals:防止某些包最终打包到bundle中(彻底不打包 要用直接cdn链接) 五、dll:(动态连接库),单独打包某些库,将多个库打包成一个chunk(先单独打包 在告诉webpack这个不用打包 提高效率,同时将该包引入到html中)

(2)优化代码运行性能:

一、缓存(contenthash) //对文件进行缓存 第二次缓存速度快 二、tree shaking (概念并非插件或者需要设置) 1、必须使用es6模块化 2、production环境有个插件自动启动tree shaking 去除在应用程序中没有应用到的代码,使代码体积更小 三、单入口:引进只有一个chunk 输出只有一个bundle

optimization:{
    splitChunks:{
       chunk:'all'      //一般是将node_module分割 单独打包成一个bundle 总共生成两个bundle
          } },              然后可以通过dll对node_module中的第三方库再一次打包 更加细化
​
   import("./text")
      .then((result) => {
         console.log('文件加载成功'+result);      //或者通过import分割指定的js代码
                  })
      .catch(() => {
           console.log("文件加载失败");
                  });

四、懒加载/预加载 五、npm i workbox-webpack-plugin -D //PWA(渐进式网络开发应用程序):离线也能访问内容 ↑ serviceworker:要处理兼容性问题 在js中注册一个serviceworker

六、pack.json报错问题 文件-首选项-设置-应用程序 - proxy Authorization 修改或添加 "http.proxyAuthorization": "false"

小tip:打包过程中被操作的模块文件叫做chunk,

很多注解是个人的理解,如果有不对的地方,各位大神多多指教。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值