Webpack详解(一)

简介: Webpack详解

Webpack详解

邂逅Webpack和打包过程

(理解)npm发布自己的包和使用包的过程

内置模块path

  • path模块用于对路径和文件进行处理,提供了很多好用的方法。
  • 我们知道在Mac OS、Linux和window上的路径时不一样的
  • window上会使用 \或者 \ 来作为文件路径的分隔符,当然目前也支持 /
  • 在Mac OS、Linux的Unix操作系统上使用 / 来作为文件路径的分隔符
  • 那么如果我们在window上使用 \ 来作为分隔符开发了一个应用程序,要部署到Linux上面应该怎么办呢?
  • 显示路径会出现一些问题
  • 所以为了屏蔽他们之间的差异,在开发中对于路径的操作我们可以使用 path 模块
  • 可移植操作系统接口(英语:Portable Operating System Interface,缩写为POSIX)
  • Linux和Mac OS都实现了POSIX接口
  • Window部分电脑实现了POSIX接口

path常见的API

  • 从路径中获取信息

路径信息

dirname

获取文件的父文件夹

basename

获取文件名

extname

获取文件扩展名


  • 路径的拼接:path.join
  • 如果我们希望将多个路径进行拼接,但是不同的操作系统可能使用的是不同的分隔符
  • 这个时候我们可以使用path.join函数
  • 拼接绝对路径:path.resolve
  • path.resolve() 方法会把一个路径或路径片段的序列解析为一个绝对路径
  • 给定的路径的序列是从右往左被处理的,后面每个 path 被依次解析,直到构造完成一个绝对路径
  • 如果在处理完所有给定path的段之后,还没有生成绝对路径,则使用当前工作目录
  • 生成的路径被规范化并删除尾部斜杠,零长度path段被忽略
  • 如果没有path传递段,path.resolve()将返回当前工作目录的绝对路径
const path = require("path")
const fileName = "D:/Desktop/Project/h5css3/h5.html"
//从路径中获取信息
//1.获取文件的父文件夹
console.log(path.dirname(fileName));//D:/Desktop/Project/h5css3
//2.获取文件名
console.log(path.basename(fileName));//h5.html
//3.获取文件扩展名
console.log(path.extname(fileName));//.html
//将多个路径拼接在一起
const path1 = "D:/Desktop/文件夹"
const path2 = "../Project/h5css3/h5.html"// 这里的../就是自动找到上一层,如果不加../就是单纯拼接在一起,想要往上几层就写几个../,而且这是会自动将 / 转义成适合MacOS和Linux的路径
console.log(path.join(path1,path2));//D:\Desktop\Project\h5css3\h5.html
//将多个路径拼接在一起,最终一定返回一个绝对路径,path.resolve
console.log(path.resolve("老铁666",path1,path2));//从右往左,形成绝对路径就不再往左推导,D:\Desktop\Project\h5css3\h5.html
//自动推导到绝对路径(./则继续往前拼接,/则到头不再拼接,推导到的绝对路径是使用当前工作目录),中间有空字符串会自动忽略
console.log(path.resolve("./----------","./XiaoYu.ts"));//D:\Desktop\Project\h5css3\----------\XiaoYu.ts

(掌握)webpack的介绍和环境搭建

认识webpack

  • 事实上随着前端的快速发展,目前前端的开发已经变的越来越复杂了:
  • 比如开发过程中我们需要通过模块化的方式来开发
  • 比如也会使用一些高级的特性来加快我们的开发效率或者安全性,比如通过ES6+、TypeScript开发脚本逻辑,通过sass、less等方式来编写css样式代码
  • 比如开发过程中,我们还希望实时的监听文件的变化来并且反映到浏览器上,提高开发的效率
  • 比如开发完成后我们还需要将代码进行压缩、合并以及其他相关的优化
  • ....
  • 但是对于很多的前端开发者来说,并不需要思考这些问题,日常的开发中根本就没有面临这些问题:
  • 这是因为目前前端开发我们通常都会直接使用三大框架来开发:Vue、React、Angular
  • 但是事实上,这三大框架的创建过程我们都是借助于脚手架(CLI)
  • 事实上Vue-CLI、create-react-app、Angular-CLI都是基于webpack来帮助我们支持模块化、less、TypeScript、打包优化等的

脚手架依赖webpack

  • 事实上我们上面提到的所有脚手架都是依赖于webpack的:

Vue webpack的webpak.config.js


React webpack的webpack.config.js


Angular webpack的build-webpack


Webpack到底是什么呢?

  • 我们先来看一下官方的解释:
webpack is a static module bundler for modern JavaScript applications
//webpack是现代JavaScript应用程序的静态模块化打包器


  • webpack是一个静态的模块化打包工具,为现代的JavaScript应用程序
  • 我们来对上面的解释进行拆解:

打包bundler

webpack可以将帮助我们进行打包,所以它是一个打包工具

静态的static

这样表述的原因是我们最终可以将代码打包成最终的静态资源(部署到静态服务器)

模块化module

webpack默认支持各种模块化开发,ES Module、CommonJS、AMD等

现代的modern

我们前端说过,正是因为现代前端开发面临各种各样的问题,才催生了webpack的出现和发展


Webpack官方的图片

Vue项目加载的文件有哪些呢?

  • JavaScript的打包:
  • 将ES6转换成ES5的语法
  • TypeScript的处理,将其转换成JavaScript
  • Css的处理:
  • CSS文件模块的加载、提取
  • Less、Sass等预处理器的处理
  • 资源文件img、font:
  • 图片img文件的加载
  • 字体font文件的加载
  • HTML资源的处理:
  • 打包HTML资源文件
  • 处理vue项目的SFC文件.vue文件

Webpack的使用前提

  • Webpack的运行是依赖Node环境的,所以我们电脑上必须有Node环境
  • 所以我们需要先安装Node.js,并且同时会安装npm
  • Node官方网站:https://nodejs.org/

Webpack的安装

  • webpack的安装目前分为两个:webpack、webpack-cli
  • 那么它们是什么关系呢?
  • 执行webpack命令,会执行node_modules下的.bin目录下的webpack
  • webpack在执行时是依赖webpack-cli的,如果没有安装就会报错
  • 而webpack-cli中代码执行时,才是真正利用webpack进行编译和打包的过程
  • 所以在安装webpack时,我们需要同时安装webpack-cli(第三方的脚手架事实上是没有使用webpack-cli的,而是类似于自己的vue-service-cli的东西)

npm install webpack webpack-cli –g # 全局安装
npm install webpack webpack-cli –D # 局部安装

(掌握)webpack基本打包-配置文件-执行脚本

Webpack的默认打包

  • 我们可以通过webpack进行打包,之后运行打包之后的代码
  • 在目录下直接执行 webpack 命令
webpack


  • 生成一个dist文件夹,里面存放一个main.js的文件,就是我们打包之后的文件:
  • 这个文件中的代码被压缩和丑化了
  • 另外我们发现代码中依然存在ES6的语法,比如箭头函数、const等,这是因为默认情况下webpack并不清楚我们打包后的文件是否需要转成ES5之前的语法,后续我们需要通过babel来进行转换和设置
  • 我们发现是可以正常进行打包的,但是有一个问题,webpack是如何确定我们的入口的呢?
  • 事实上,当我们运行webpack时,webpack会查找当前目录下的 src/index.js作为入口
  • 所以,如果当前项目中没有存在src/index.js文件,那么会报错
  • 当然,我们也可以通过配置来指定入口和出口
//entry:入口
npx webpack --entry ./src/main.js --output-path ./build//我指定打包的入口为main.js跟出口为build文件夹


创建局部的webpack

  • 前面我们直接执行webpack命令使用的是全局的webpack,如果希望使用局部的可以按照下面的步骤来操作
  • 第一步:创建package.json文件,用于管理项目的信息、库依赖等
npm init//使用pnpm也行
  • 第二步:安装局部的webpack
npm install webpack webpack-cli -D
  • 第三步:使用局部的webpack
npx webpack
  • 第四步:在package.json中创建scripts脚本,执行脚本打包即可
"scripts":{
    "build":"webpack"
}
npm run build//终端执行命令

不喜欢打包后的文件叫做main.js,我想叫做xiaoyu.js,能不能修改,当然可以

npx webpack --output-filename xiaoyu.js

不喜欢入口文件叫做index.js,想叫做main.js,如何修改

npx webpack --entry ./src/main.js//入口修改为main.js

Webpack配置文件

  • 在通常情况下,webpack需要打包的项目是非常复杂的,并且我们需要一系列的配置来满足要求,默认配置必然是不可以的
  • 我们可以在根目录下创建一个webpack.config.js文件,来作为webpack的配置文件:

这个配置文件的名字也可以进行更改,但是更改需要修改配置,否则会报错:


npx webpack --config wk.config.js//设置webpack的配置文件为wk.config.js
//嫌麻烦可以将他放到package.json里的scripts里面,让npm run xxx进行启动修改配置跟启动打包
"scripts":{
    "build":"webpack --config wk.config.js"
}


const path = require('path')
//导出配置信息
module.exports = {
    entry:"./src/main.js",//指定打包的入口位置
    output:{
        filename:"bundle.js"//指定打包后的出口文件
        path:path.resolve(__dirname,"./build")//指定打包后的文件夹名字,使用path是因为这里必须是绝对路径,使用resolve方法,__dirname是用来获取当前的所在路径
    }
}

继续执行webpack命令,依然可以正常打包

npm run build

(理解)webpack的形成的依赖图结构

Webpack的依赖图

  • webpack到底是如何对我们的项目进行打包的呢?
  • 事实上webpack在处理应用程序时,它会根据命令或者配置文件找到入口文件
  • 从入口开始,会生成一个 依赖关系图,这个依赖关系图会包含应用程序中所需的所有模块(比如.js文件、css文件、图片、字体等)
  • 然后遍历图结构,打包一个个模块(根据文件的不同使用不同的loader来解析)

loader:webpack默认情况下是只对我们的js进行打包,如果我们想要我们文件里面也包括了css文件、图片、字体等,就需要用到loader来解析了


图结构形式的打包

(掌握)webpack的css处理和loader的使用

编写案例代码

  • 我们创建一个component.js
  • 通过JavaScript创建了一个元素,并且希望给它设置一些样式;
import "../css/stype.css";
//之所以可以不用写from,是因为我们并不使用它,而是将css导入我们的依赖图中


继续编译命令 npm run build

css-loader的使用

  • 上面的错误信息告诉我们需要一个loader来加载这个css文件,但是loader是什么呢?
  • loader 可以用于对模块的源代码进行转换
  • 我们可以将css文件也看成是一个模块,我们是通过import来加载这个模块
  • 在加载这个模块时,webpack其实并不知道如何对其进行加载,我们必须制定对应的loader来完成这个功能
  • 那么我们需要一个什么样的loader呢?
  • 对于加载css文件来说,我们需要一个可以读取css文件的loader
  • 这个loader最常用的是css-loader
//这些loader都是在webpack配置文件(webpack.config.js)里的module的rules
//可以在里面写上匹配.vue的文件就使用vue-loader去处理
//css,ts,tsx都是这样子处理的(这就是webpack的强大之处,不断的集成。也是loader的本质)
  • css-loader的安装:
npm install css-loader -D

css-loader的使用方案

  • 如何使用这个loader来加载css文件呢?有三种方式:
  • 内联方式;
  • CLI方式(webpack5中不再使用)
  • 配置方式
  • 内联方式:内联方式使用较少,因为不方便管理
  • 在引入的样式前加上使用的loader,并且使用!分割
import "css-loader!../css/style.css"//一般也不采用
  • CLI方式
  • 在webpack5的文档中已经没有了--module-bind
  • 实际应用中也比较少使用,因为不方便管理(淘汰了)

loader配置方式

  • 配置方式表示的意思是在我们的webpack.config.js文件中写明配置信息:
  • module.rules中允许我们配置多个loader(因为我们也会继续使用其他的loader,来完成其他文件的加载)
  • 这种方式可以更好的表示loader的配置,也方便后期的维护,同时也让你对各个Loader有一个全局的概览
  • module.rules的配置如下:
  • rules属性对应的值是一个数组:[Rule]
  • 数组中存放的是一个个的Rule,Rule是一个对象,对象中可以设置多个属性:
  • test属性:用于对 resource(资源)进行匹配的,通常会设置成正则表达式
  • use属性:对应的值时一个数组:[UseEntry]
  • UseEntry是一个对象,可以通过对象的属性来设置一些其他属性
  1. loader:必须有一个 loader属性,对应的值是一个字符串
  2. options:可选的属性,值是一个字符串或者对象,值会被传入到loader中
  3. query:目前已经使用options来替代

传递字符串(如:use: [ 'style-loader' ])是 loader 属性的简写方式(如:use: [ { loader: 'style-loader'} ])

  • loader属性: Rule.use: [ { loader } ] 的简写。

Loader的配置代码

//webpack.config.js文件继续深入(将去掉之前写过的注释,强调现有的注释)
const path = require('path')
//导出配置信息
module.exports = {
    entry:"./src/main.js",
    output:{
        filename:"bundle.js"
        path:path.resolve(__dirname,"./build")
    },
    module:{//模块配置:
        rules:[//规则很多,所以是数组类型里用对象用来存放
            //{},{},{}用来存放多种类型的loader
            {
                //告诉webpack,我们要匹配什么文件
                test:/\.css$/ //这里填入的是正则,用来匹配我们的后缀文件
                //use中多个loader的使用顺序是从后往前的
                use:[//告诉webpack用什么loader来处理,为什么用数组,是因为有时候一个loader是处理不完的
                  {loader:"css-loader"}//这时候你需要npm下载css-loader -D,在开发的时候才会用到
                ]
            }
        ]
    }
}

认识style-loader

  • 我们已经可以通过css-loader来加载css文件了
  • 但是你会发现这个css在我们的代码中并没有生效(页面没有效果)
  • 这是为什么呢?
  • 因为css-loader只是负责将.css文件进行解析,并不会将解析之后的css插入到页面
  • 如果我们希望再完成插入style的操作,那么我们还需要另外一个loader,就是style-loader
  • 安装style-loader:
npm install style-loader -D

配置style-loader

  • 那么我们应该如何使用style-loader:
  • 在配置文件中,添加style-loader
  • 注意:因为loader的执行顺序是从右向左(或者说从下到上,或者说从后到前的),所以我们需要将style-loader写到css-loader的前面
use:[//告诉webpack用什么loader来处理,为什么用数组,是因为有时候一个loader是处理不完的
    {loader:"style-loader"},
    {loader:"css-loader"}//这时候你需要npm下载css-loader -D,在开发的时候才会用到
]
  • 重新执行编译npm run build,可以发现打包后的css已经生效了:
  • 当前目前我们的css是通过页内样式的方式添加进来的
  • 后续我们也会讲如何将css抽取到单独的文件中,并且进行压缩等操作

(掌握)webpack的less文件处理

刚刚rules里面的use简写方式

//简写1:如果loader只有1个,可以直接省略use
loader:"css-loader"
//简写2:
use:[
    {loader:"css-loader",options:{}}//之所以写对象,这是因为这里面除了写loader,还能写其他配置,比如options之类
    //如果不写其他配置,那也可以省略掉
    loader:"style-loader"
]

如何处理less文件?

  • 在我们开发中,我们可能会使用less、sass、stylus的预处理器来编写css样式,效率会更高
  • 那么,如何可以让我们的环境支持这些预处理器呢?
  • 首先我们需要确定,less、sass等编写的css需要通过工具转换成普通的css
  • 比如我们编写如下的less样式:
@fontSize:30px;
@fontWeight:700;
.content {
    font-size:@fontSize;
    font-weight:@fontWeight;
}

Less工具处理

  • 我们可以使用less工具来完成它的编译转换:
npm install less -D


  • 执行如下命令:
npx lessc ./src/css/title.less title.css


less-loader处理

  • 但是在项目中我们会编写大量的css,它们如何可以自动转换呢?
  • 这个时候我们就可以使用less-loader,来自动使用less工具转换less到css
npm install less-loader -D
  • 配置webpack.config.js

我们配置的时候除了写less之外,我们还写了css跟style是因为,less-loader只是将less语法转化成css语法,但是css语法还得进行处理的,使用css的loader处理css语法,最后使用style的loader将其引入使用


{
    test:/\.less$/,//处理less文件
    use:[
      {loader:"style-loader"},
      {loader:"css-loader"},
      {loader:"less-loader"},
    ]
}

(理解)webpack中postcss-loader的

认识PostCSS工具

  • 什么是PostCSS呢?
  • PostCSS是一个通过JavaScript来转换样式的工具
  • 这个工具可以帮助我们进行一些CSS的转换和适配(有些属性是由兼容问题的),比如自动添加浏览器前缀、css样式的重置
  • 但是实现这些功能,我们需要借助于PostCSS对应的插件(不安装的话PostCSS不会生效)
  • 如何使用PostCSS呢?主要就是两个步骤:
  • 第一步:查找PostCSS在构建工具中的扩展,比如webpack中的postcss-loader
  • 第二步:选择可以添加你需要的PostCSS相关的插件

postcss-loader

  • 我们可以借助于构建工具:
  • 在webpack中使用postcss就是使用postcss-loader来处理的
  • 我们来安装postcss-loader:
npm install postcss-loader -D
  • 我们修改加载css的loader:(配置文件已经过多,给出一部分了)
  • 注意:因为postcss需要有对应的插件才会起效果,所以我们需要配置它的plugin;
{
    test:/\.css$/,//处理less文件
    use:[
      {loader:"style-loader"},
      {loader:"css-loader"},
      {loader:"postcss-loader",
       options:{//loader会读取这里面的内容,options是选项们的意思
         postcssOptions:{
           plugins:[//插件们
             "autoprefixer"//使用这个插件对loader做出某种转换(添加前缀的插件)
           ]
         }
       }
      }
    ]
}

单独的postcss配置文件

  • 因为我们需要添加前缀,所以要安装autoprefixer:
npm install autoprefixer -D


  • 我们可以将这些配置信息放到一个单独的文件中进行管理:(就不会让上面配置文件里面套太多层了,看着都密密麻麻的)
  • 在根目录下创建postcss.config.js(名字不能乱改,会自动寻找到这个名字的文件,就我们前面说的从.js开始找,没找到就找.json,node文件)
//postcss.config.js文件
module.exports = {//暴露出去
  //不用写postcssOptions,因为这个不是独立起来的(没有独立于webpack),postcss内部会自动寻找到
  plugins:[
    require("autoprefixer")//引入
  ]
}
{
    test:/\.css$/,//处理less文件
    use:[
      {loader:"style-loader"},
      {loader:"css-loader"},
      {loader:"postcss-loader"}//然后默认填写就行了,因为我们在另外的配置文件中已经写了plugins的东西了,会自动去读取,less如果也想要处理的话,也要加上
    ]
}

postcss-preset-env

  • 事实上,在配置postcss-loader时,我们配置插件并不需要使用autoprefixer
  • 我们可以使用另外一个插件:postcss-preset-env
  • postcss-preset-env也是一个postcss的插件(因为有一些插件是使用postcss基本上都会使用的,所以postcss就将他集成了,叫做预设环境,已经包含了常用插件跟插件环境的配置了)
  • 它可以帮助我们将一些现代的CSS特性,转成大多数浏览器认识的CSS,并且会根据目标浏览器或者运行时环境添加所需的polyfill
  • 也包括会自动帮助我们添加autoprefixer(所以相当于已经内置了autoprefixer)
  • 首先,我们需要安装postcss-preset-env:
npm install postcss-preset-env -D


  • 之后,我们直接修改掉之前的autoprefixer即可:
plugins:[
  requires("postcss-preset-env")
]


  • 注意:我们在使用某些postcss插件时,也可以直接传入字符串
module.exports = {
  plugins:[
    "postcss-preset-env"
  ]
}


Webpack打包图片-JS-Vue

(掌握)webpack对图片资源的基本处理

加载图片案例准备

  • 为了演示我们项目中可以加载图片,我们需要在项目中使用图片,比较常见的使用图片的方式是两种:
  • img元素,设置src属性
  • 其他元素(比如div),设置background-image的css属性
const zznhImage = new Image()//创建一个image元素
zznhImage.src = zznhImg;
element.appendChild(zznhImage);
//3.增加一个div用来存放图片
const bgDiv = document.createElement('div')
bgDiv.style.width = 200 + 'px'
bgDiv.style.height = 200 + 'px'
bgDiv.style.display = 'inline-block'
bgDiv.className = 'bg-image'
bgDiv.style.backgroundColor = 'red'
element.appendChild(bgDiv)

认识asset module type

  • 我们当前使用的webpack版本是webpack5:
  • 在webpack5之前,加载这些资源我们需要使用一些loader,比如raw-loader 、url-loader、file-loader
  • 在webpack5开始,我们可以直接使用资源模块类型(asset module type),来替代上面的这些loader
  • 资源模块类型(asset module type),通过添加 4 种新的模块类型,来替换所有这些 loader:
  • asset/resource 发送一个单独的文件并导出 URL
    之前通过使用 file-loader 实现
    asset/resource = 资产里的资源
  • asset/inline 导出一个资源的 data URI
    之前通过使用 url-loader 实现
  • asset/source 导出资源的源代码(不常用)
    之前通过使用 raw-loader 实现
  • asset 在导出一个 data URI 和发送一个单独的文件之间自动选择
    之前通过使用 url-loader,并且配置资源体积限制实现
//引入图片模块,现在已经不再使用loader的方式来执行这些部分了,以前是使用file-loader。现在新版本使用处理还可能报错。但现在webpack已经内置如何处理文件了。但如果你直接运行还是会报错的,因为webpack将所有图片格式的文件也当作了js模块去处理了,毕竟webpack也不知道怎么去处理,需要我们去告诉webpack
imports zznhImage form "./xxx/你的图片地址"
//image元素
//const imgEl = document.createElement('img')

asset module type的使用

  • 比如加载图片,我们可以使用下面的方式:(没错,我们要来处理图片了,要告诉webpack怎么去做)
{
  test:/\.(img|svg|ipg|jpe?g|gif)$/ //识别各种图片的后缀格式,让webpack找到这些文件
  type:"asset/resource"//告诉webpack这是资源类型,将找到的这些文件当作资源类型处理(资源类型是什么在上面有写出来)
}
  • 但是,如何可以自定义文件的输出路径和文件名呢?
  • 方式一:修改output,添加assetModuleFilename属性

好处举例:这样自己制定规则就可以防止,打包后的图片文件名字跟原来的文件名字已经牛头不对马嘴,完全对不上了。你可以自己设定容易让自己区分的规则来打包。但一般很少在这里配置,我们一般采用第二种配置方法


  • 方式二:在Rule中,添加一个generator属性,并且设置filename

  • 我们这里介绍几个最常用的placeholder:
  • [ext]: 处理文件的扩展名(后缀名,比如.svg,.js,.html之类的)
  • [name]:处理文件的名称(原来图片的名字)
  • [hash]:文件的内容,使用MD4的散列函数处理,生成的一个128位的hash值(32个十六进制)

哈希值最好保存下来,哈希值是唯一的,防止图片不小心重复,[hash:6]就是只使用前6位哈希值(基本上也够用了)


最前面写上img/,就会自己生成一个img文件夹,然后将图片放进去


Webpack详解(二)https://developer.aliyun.com/article/1470454

目录
相关文章
|
1月前
|
缓存 JavaScript
webpack之SplitChunksPlugin
webpack之SplitChunksPlugin
19 0
|
30天前
|
JSON JavaScript 前端开发
|
4月前
|
JavaScript 前端开发
webpack
webpack
37 0
webpack
|
8月前
|
JSON 缓存 前端开发
webpack相关详细讲解。
webpack相关详细讲解。
|
8月前
|
缓存 前端开发 JavaScript
浅谈webpack
浅谈webpack
87 0
|
前端开发 JavaScript
关于 Webpack 的介绍,什么是 Webpack?
Webpack 是一款现代化的前端构建工具,它可以将你的项目中的多个 JavaScript 模块打包成一个或多个 bundle 文件,同时还可以处理各种类型的静态资源,比如 CSS、图片等等。 Webpack 最初是由 Tobias Koppers 开发的,目前已经成为了前端开发中使用最广泛的构建工具之一。
114 0
|
缓存 算法
webpack的chunkFilename详细说明
webpack的chunkFilename详细说明
192 0
|
JavaScript 前端开发
从了解到使用webpack
Webpack本质上是一种前端资源编译,打包工具
69 0
|
前端开发 JavaScript
1、webpack
1、webpack
69 0
|
缓存 JavaScript 前端开发
Webpack
本质上,*webpack* 是一个现代 JavaScript 应用程序的*静态模块打包器(module bundler)*。当 webpack 处理应用程序时,它会递归地构建一个*依赖关系图(dependency graph)*,其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 *bundle*。
Webpack