Webpack

什么webpack

webpack文档地址:概念 | webpack 中文文档

本质上,webpack是一个用于现代Javascript应用程序的静态模块打包工具,当webpack处理应用程序时,它会在内部从一个或多个入口点构建一个依赖图(dependency graph),然后将你项目中所需的每一个模块组合成一个或多个bundles,他们均为静态资源,用于展示你的内容。

静态模块:指的是编写代码过程中的html、css、js、图片等固定内容的文件

打包:把静态模块内容,压缩,整合(把多个css文件、或js文件整合到一个文件中,减少浏览器http的请求次数,让用户更快的访问到页面),转译(把less、sass转成css代码;把ES6+降级成ES5;支持多种模块标准语法)等(前端工程化)

使用Webpack

需求:封装utils包,校验手机号长度和验证码长度,在src/index.js中使用并打包观察

步骤:

  1.  新建并初始化项目,编写业务源代码  npm init -y
  2. 下载webpack webpack-cli到当前项目中(版本独立),并配置局部自定义命令

npm i webpack webpack-cli --save-dev

配置局部自定义指令

"scripts":{

   "buold":"webpack"

}

     3 运行打包命令(npm run build),自动产生dist分发文件夹(压缩和优化后,用于最终运行的代码)

 修改webpack的入口和出口

  • 项目根目录,新建webpack.config.js配置文件
  • 导出配置对象,配置入口,出口文件的路径
  • 重新打包观察

注意:只有和入口产生直接/间接的引入关系,才会被打包

const path = require('path')

module.exports = {
  //入口
  entry: path.resolve(__dirname, 'src/login/index.js'),
  // 出口
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: './login/index.js',
    clear: true  //生成打包内容之前,清空输出目录,在版本5.2.0以上的版本
  }
}

自动生成html文件

插件html-webpack-plugin 在webpack打包时生成html文件HtmlWebpackPlugin | webpack 中文文档

下载html-webpack-plugin本地软件包:

配置webpack.config.js让webpack拥有插件功能

npm install --save-dev html-webpack-plugin

 webpack.config.js的文件内容

const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
  //入口
  entry: path.resolve(__dirname, 'src/login/index.js'),
  // 出口
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: './login/index.js',
    clean: true  //生成打包内容之前,清空输出目录
  },
  // 插件:给webpack提供更多的功能
  plugins: [
    new HtmlWebpackPlugin({
      template: path.resolve(__dirname, 'public/login.html'), //模板文件
      filename: path.resolve(__dirname, 'dist/login/index.html') //输出文件
    })
  ]
}

生成后的html文件也会自动引入js文件

<script defer="defer" src=".././login/index.js"></script>

 打包CSS代码

注意:Webpack默认只识别js代码

加载器:css-loader :解析css代码

加载器:style-loader:把解析后的css代码插入到DOM

css-loader | webpack 中文文档

安装 :npm install style-loader css-loader --save-dev

 将CSS文件代码引入到src/login/index.js中(压缩转移处理等)

下载css-lader和style-loader本地软件包

配置webpack.config.js让webpack拥有该加载器功能

在webpack.config.js文件中添加如下代码

// 加载器(让webpack识别更多模块文件内容)
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: ['style-loader', 'css-loader']
      }
    ]
  }

优化-提取css代码

好处:css文件可以被浏览器缓存,减少js文件体积

注意:不能和style-loader一起使用

文档:https://webpack.docschina.org/plugins/mini-css-extract-plugin/

npm install --save-dev mini-css-extract-plugin

配置webpack.config.js

const MiniCssExtractPlugin = require('mini-css-extract-plugin')

plugins: [

    new HtmlWebpackPlugin({

      template: path.resolve(__dirname, 'public/login.html'), //模板文件

      filename: path.resolve(__dirname, 'dist/login/index.html') //输出文件

    }),

    new MiniCssExtractPlugin() //生成css文件

  ],

  // 加载器(让webpack识别更多模块文件内容)

  module: {

    rules: [

      {

        test: /\.css$/i,

        // use: ['style-loader', 'css-loader']

        use: [MiniCssExtractPlugin.loader, "css-loader"]

      }

    ]

  }

 优化-压缩过程

使用 css-minimizer-webpack-plugin插件
浮动地方

npm i   css-minimizer-webpack-plugin --save-dev

const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");

optimization: {
    // 最小化
    minimizer: [
      // 对于 webpack@5 你可以使用 `...` 语法来扩展现有的 minimizers
      // (i.e. `terser-webpack-plugin`),请将下一行注释掉,保证js代码还能被压缩处理
      `...`,  //不用这个,就需要用内置的插件terser-webpack-plugin
      new CssMinimizerPlugin(),
    ],
  },

 打包less

npm install less less-loader --save-dev

module: {
    rules: [
      {
        test: /\.css$/i,
        // use: ['style-loader', 'css-loader']
        use: [MiniCssExtractPlugin.loader, "css-loader"]
      }, {
        test: /\.less$/i,
        use: [
          // 'style-loader', 这个不能和MiniCssExtractPlugin.loader混用
          MiniCssExtractPlugin.loader,
          'css-loader',
          'less-loader'
        ]

      }
    ]
  },

  打包图片

资源模块 | webpack 中文文档
资源模块:webpack5内置资源模块(字体、图片等)打包,无需额外loader
步骤:
 配置webpack.config.js让webpack拥有图片打包功能
type:"asset" : 模式的判定方式,自己判断采用哪种方式

作用:
base64   =》减少http请求,让网页加载快一些,大于8KB,因为资源模块转为base64字符串的时候,可能会让这个文件真实的体积大于20%到30%之间,

module: {
   rules: [
      {
        test: /\.(png|jpg|gif)$/i,
        type: 'asset', //让它自己判定是那种方式
        generator:{
          filename:"assets/[hash][ext][query]"
       }
      },
   ]
 },

占位符[hash]对模块内容做算法计算,得到映射的数字字母组合的字符串
占位符[ext]使用当前模块原本的占位符,例如:.png,.jpg等字符串
占位符[query]保留引入文件时代码中查询参数(只有URL下生效)
注意:js中引入本地图片资源要用import方式(如果时网络图片http地址,字符串可以直接写)

 搭建开发环境

问题:之前改代码,需要重新打包才能运行查看,效率很低,
开发环境:配置webpack-dev-server快速开发应用程序
作用:启动web服务,自动检测代码变化,热更新到网页
注意:dist目录和打包内容是在内存里(更新快)
步骤
下载   npm i webpack-dev-server --save-dev
设置模式位开发模式,并配置自定义命令
module.exports={ ...   mode:'development'}
在pakage.json文件中修改
"scripts":{
  "dev":"webpack serve --open"
}
使用npm run dev来启动开发服务器,试试热更新效果
注意1:webpack-dev-server 借助http模块创建8080默认web服务,
注意2:默认以public文件夹作为服务器根目录,访问该目录下的index.html
注意3:webpack-dev-server根据配置,打包相关代码在内存当中,以output.path的值作为服务器目录(所以可以直接拼接访问dist目录下的内容)
浏览器直接输入localhost:8080/login/index.html
location.href = '/login/index.html'  在public/index.html里面写如上代码,直接跳转到打包好的html文件内容
打包模式
打包模式:告知webpack使用相应模式的内置优化
分类

模式名称模式名字特点场景
开发模式development调试代码,实时加载,模块热替换等本地开发
生产模式production压缩代码,资源优化,更轻量等打包上线

 设置:
方式一:在webpack.config.js配置文件设置mode选项
方式二:在package.json命令行设置mode参数
注意:命令行设置的优先级高于配置文件中的,推荐用命令行设置
推荐在package.json文件中进行修改
"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack --mode=production",
    "dev": "webpack serve --open --mode=development"
  },
打包模式的应用
需求:在开发模式下用style-loader内嵌更快,在生成模式下提取css代码
方案一:webpack.config.js配置导出函数,但是局限性大(只接收2中模式)
方案二:借助cross-env(跨平台通用)包命令,设置参数区分环境
步骤
  下载cross-env软件包到当前项目  npm i cross-env --save-dev
  配置自定义命令,传入参数名和值(会绑定到process.env对象下)

"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "cross-env NODE_ENV=production webpack --mode=production",
    "dev": "cross-env NODE_ENV=development webpack serve --open --mode=development"
  },


  在webpack.config.js区分不同环境使用不同配置

rules: [
      {
        test: /\.css$/i,
        // use: ['style-loader', 'css-loader']
        use: [process.env.NODE_ENV == 'production' ? MiniCssExtractPlugin.loader : 'style-loader', "css-loader"]
      }, {
        test: /\.less$/i,
        use: [
          // 'style-loader',
          process.env.NODE_ENV == 'production' ? MiniCssExtractPlugin.loader : 'style-loader',
          'css-loader',
          'less-loader'
        ]

      },
     ....
    ]

  方案3:配置不同的webpack.config.js(适用于多种模式差异较大情况)

 前端-注入环境变量

需求:前端项目中,开发模式下打印语句生效,生产模式下打印语句失效
问题:cross-env设置的只在Node.js环境生效,前端代码无法访问process.env.NODE_ENV
解决:使用Webpack内置的DefinePlugin插件
DefinePlugin | webpack 中文文档

const webpack = require('webpack');

module.exports = {
  new webpack.DefinePlugin({
      // key是注入到打包后的前端js代码中作为全局变量
      // value是变量对应的值在cross-env注入在node.js中的环境变量字符串
      "process.env.NODE_ENV": JSON.stringify(process.env.NODE_ENV)
    })
}


在index.js中设置console.log不起效
// 在这个后面的才会失效
if (process.env.NODE_ENV === 'production') {
  console.log = function () { }
}

 开发环境调错-source map

问题:代码被压缩和混淆,无法正确定位源代码位置(行数和列数)
source.map: 可以准确追踪error和warning在原始代码的位置
设置:webpack.config.js配置devtool选项
module.exports={
    ....
   devtool:'inline-source-map'
}
inline-source-map选项:把源码的位置信息一起打包在js文件内
注意:source map仅适用于开发环境,不要再生产环境使用,(防止被轻易查看源码位置)
if (process.env.NODE_ENV === 'development') {
  config.devtool = 'inline-source-map'
}
module.exports = config

 解析别名 alias

解析别名:配置模块如何解析,创建import引入路径的别名,类确保模块引入变得更简单
解决:再webpack.config.js中配置解析别名@

//解析别名
  resolve: {
    alias: {
      '@': path.resolve(__dirname, 'src')
    }
  }

 优化-CDN使用

cdn定义:内容分发网络,指的是一组分布再各个地区的服务器
作用:把静态资源/第三方库放在CDN网络中各个服务器中,共用户就近请求获取
好处:减轻自己服务器请求压力,就近请求物理延迟低,配套缓存策略
需求:开发模式使用本地第三方库,生产模式下使用CDN加载引入
步骤:
 在html中引入第三方库的CDN地址并用模板语法判断
配置webpack.config.js中externals外部扩展选项(防止某些import的包被打包)
步骤:
在html中引入cdn,并用模板语法判断

  <% if(htmlWebpackPlugin.options.useCdn) { %>
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.2.3/css/bootstrap.min.css" rel="stylesheet">
    <% } %>

<% if(htmlWebpackPlugin.options.useCdn) { %>
    <script src="https://cdn.bootcdn.net/ajax/libs/axios/1.3.6.axios.min.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.2.3/js/bootstrap.min.css"></script>
    <% } %>

在webpack.config.js中配置useCdn的值和相关配置

const config={
  plugins: [
    new HtmlWebpackPlugin({
      template: path.resolve(__dirname, 'public/login.html'), //模板文件
      filename: path.resolve(__dirname, 'dist/login/index.html'), //输出文件
      useCdn: process.env.NODE_ENV === 'production' //生产模式下使用cdn引入的地址
    }),
  ]
}

//生产环境下使用相关配置
if (process.env.NODE_ENV === 'production') {
  config.externals = {
    // key: import from 语句后面的字符串
    // value:留在原地的全局变量(最好和cdn在全局暴露的变量一致)
    'bootstrap/dist/css/bootstrap.min.css': 'bootstrap',
    'axios': 'axios'
  }
}

 多页面打包

 单页面:单个html文件,切换DOM的方式实现不同业务逻辑展示,
多页面:多个html文件,切换页面实现不同业务逻辑展示

const config = {

  entry: {

    "模块名1": path.resolve(__dirname, 'src/入口1.js'),

    "模块名2": path.resolve(__dirname, 'src/入口2.js')

  },

  output: {

    path: path.relative(__dirname, 'dist'),

    filename: './[name]/index.js' // 多个模块自己选择到对应的文件夹下

  },

  plugins: [

    new HtmlWebpackPlugin({

      template: './public/页面2.html',//模板文件

      filename: './路径/index.html', //输出文件,不能用[name]

      chunks: ['模块名2']

    }),

    new HtmlWebpackPlugin({

      template: './public/页面1.html',

      filename: './路径/index.html', //输出到对应的文件夹下

      chunks: ['模块名1'] // 引入那些打包后的模块(和entry的key一致)

    }),

    new MiniCssExtractPlugin({

      filename: './[name]/index.css'

    })

  ]

}

 

 分割公共代码

需求:把2个以上页面引用的公共代码提取

步骤:

1 配置webpack.config.js的splitChunks分割功能

optimization: {

    splitChunks: {

      chunks: 'all', //所有模块动态非动态移入的都分割分析

      cacheGroups: { //分隔组

        commons: { //抽取公共模块

          minSize: 0, // 抽取的chunk最小大小字节

          minChunks: 2, //最小引用数

          reuseExistingChunk: true, //当前chunk包含已从主bundle中拆分出的模块,则它将被重用

          name(module, chunks, cacheGroupKey) { //分离出模块文件名

            const allChunksNames = chunks.map((item) => item.name).join('~') //模块名1~模块名2

            return `./js/${allChunksNames}` //输出到dist目录下位置

          }

        }

      }

    }

  }

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值