从零基础学习【Webpack4】(前端必会)-阿里云开发者社区

开发者社区> 开发与运维> 正文

从零基础学习【Webpack4】(前端必会)

简介: 近在咫尺的webpack5马上就要发布,在这个4的尾巴阶段,留一份一看就懂的教程。但无论是哪个版本,只是升级了而已,总而言之,webpack是一个高级前端工程师必会的(虽然博主不是)。博主也在不断学习中,复习到webpack,想借此博客写一篇容易看懂的。

近在咫尺的webpack5马上就要发布,在这个4的尾巴阶段,留一份一看就懂的教程。但无论是哪个版本,只是升级了而已,总而言之,webpack是一个高级前端工程师必会的(虽然博主不是)。
博主也在不断学习中,复习到webpack,想借此博客写一篇容易看懂的。因为如果你是小白,其他的博客文章,自己很难看懂。
本次,我们从一个空文件夹开始,一步一步的搭建一个webpack,如果你静下心来,好好看看这篇文章,相信你会有收获。开发前提:安装nodeJs。

本篇文章的学习知识(并非按照下边顺序讲解):

1、webpack的作用。
2、自己搭建webpack项目
3、webpack的默认配置(entry/output等等)。
4、hash和chunkhash
5、webpack自定义配置。
6、loader模块处理。
7、plugin插件。
8、mode(production生产环境和development开发环境)。

以上这些就是打算今天要学习的,几乎学习完了,自己也就都懂了。所以知识不少,跟住思路,我们一起来学习。

------------ 一、webpack的作用: ----------

webpack 的主要目标是将 JavaScript 文件打包在一起,打包后的文件用于在浏览器中使用。
曾经的前端并没有现在这么复杂,如今我们前端的发展,已经到了承接各种需求的地步,那么我们现在开发代码很多,逻辑也很多,慢慢的一些技术或者插件也就随之而来。比如vue或react,这两种开发方式都是模块化开发,模块开发对我们前端来说固然方便了很多,但上线后在加载上会出现一些性能问题。这就是模块过多,请求数量引起的。

那工程师想到的办法就是,将这些模块,打包成一个文件,这样将请求数量降到最低,提高加载速度。所以打包工具就出来了。

webpack一大亮点是,它能分析代码结构,按需打包,会将无用的代码过滤掉,只打包有用到的代码,减少体积。这也是取代了gulp的原因(据说gulp会将有用的没用的代码或插件都打包在一起)。

------------ 二、使用webpack搭建项目 ----------

我们今天不弄的那么复杂,就简单搭建一个有html、css、js和图片的一个项目,从建立一个空文件夹开始搭建一个项目。这种教程还是比较少的,最少需要掉三根头发才能写完教程(博主先去哭一会)。

1、首先,我们建立一个空文件夹,记住文件夹的名字不要是webpack,否则将会创建不成功。名字随便起(本文先以博主名字建个文件夹:villin)

image

2、进入到这个文件夹,打开你的终端,空文件夹第一步需要生成一个叫package.json的文件。它是“做肾”的?
package.json就是管理你本地安装的npm包,用于定义了这个项目所需要的各种模块,以及项目的配置信息。如版本、描述、作者、运行脚本(如:npm run dev)等等。最主要的是我们有了这个模块,稍后下载的时候,就可以在文件夹中自动生成一个node-modules文件夹。然后会将以后的模块下载到node-modules文件夹中。
简单来说,你可以把它看成是一个项目说明书,上边记录了这个项目的所有权,我们下载第三方插件时,也会记载到这里,以后我们传文件时,可以删掉node-modules文件包,但只要有package.json这个文件,npm i 时就可以重新按照这个说明说下载回来。所以package.json这个文件始终都不能删!!!

运行: npm init

运行之后,第一次会询问一些问题,我们可以设置,也可以一直按回车键。之后我们就生成了package.json文件夹了,可以打开看一下:

image

我们可以看一下,里边有一个devDependencies字段,这里放着的就是我们这个项目所用到的插件,每次安装一个插件时,就会被记录当这里。

3、安装webpack:

不建议全局安装,就是后边带一个-g的这种,原因是:我们一旦全局安装后,所有项目都会用到这个版本的,如果你有其他的项目用到的是旧版本,那么会有冲突。

所以我们进入到这个文件夹后,直接安装即可。除了安装webpack,在V4+版本时,还需要安装webpack-cli,所以我们一起安装:

npm i -D webpack webpack-cli

4、安装后看一下目录,是这个样子:

image

5、现在我们就可以运行webpack了,这里涉及到了一个知识点,自定义构建脚本命令,我们进入到package.json文件,里边有一个“scripts”字段,里边就是自定义的命令,因为这里除了默认的,就没有命令了,我们没办法运行。所以我们想要运行webpack,就构建一条命令,然后运行它就可以。

在“scripts”字段里添加一个命令,"key":"value"的形式,我们随便起一个名字叫dev,后边放上webpack命令就可以了。

image

6、我们刚才添加了命令,现在就可以运行npm run dev了,记住,定义了什么,就可以npm run 什么。这句话比较粗糙,但你能明白就好。

保存运行一下:npm run dev。发现会报错:

image

报错的原因并不是因为我们的命令写错了,看上边的提示:没有找到./src文件

这就是为什么我们开发时,要把页面写在src中的原因。webpack在打包时,会自动的识别src目录下的根目录index.js,所以这都是必须要有的。为了防止报错,我们就建立一个src文件夹,里边放入index.js文件,并且在index.js中随便写点内容,就写一个:

console.log("villin你好")

创建文件,如下:

image

我们重新运行:npm run dev。运行成功。

我们这个时候再返回来看一下文件目录,会多出一个dist文件夹,里边会有一个main.js文件,这就是运行了webpack打包后的文件。打包成功!如果你也跟到这里,没有任何问题的话,恭喜你,可以自己打包成功了,我们继续进行;如果有问题,不要往下进行,返回找到问题后继续哈哈image

image

------------ 三、webpack配置 ----------

1、webpack的配置文件叫webpack.config.js,我们在构建项目时,并没有这个文件,但这个文件确实真实存在的,webpack在打包时会自动识别叫这个名字的文件,如果有,就按照这里边配置的打包,如果没有,就按照它自己默认的打包。我们开发时需要配置,所以我们需要自己创建出来,和 package.json 同级,我们创建这个文件:

image

2、因为webpack在默认情况下,只打包src下边的index.js文件,但我们开发会有很多其他文件,我们就需要配置了,所以我们现在开始学习怎样配置这个文件。在webpack.config.js文件中,我们的配置项,写在module.exports对象中:

image

基本配置:entry和output

entry是入口的配置,webpack打包时,需要问,我打包哪一个文件啊?那么我们就把我们想打包的文件,放这里,webpack这个小可爱就知道了,就会将这个文件,以及这个文件引入的相关的一些文件,将它打包。打包成一个文件。然后又问,我打包后放在哪里呀?那么我们就把想要放的位置写在output中,这个小可爱就会按照我们给它的路径,放到这个里边。那怎么写呢?

entry可以写成字符串的形式,或者写成数组的形式,或者写成对象的形式,这三种形式都可以。
output一般我们写成对象的形式,重要的一点是,输出的路径一定一定要写成绝对路径

我们先写entry,先用字符串的模式写,那我们打包哪一个文件呢?是src下边的index.js文件,如下:

image

如上图,output写成对象的形式,默认有两个参数,path和filename,path就是我们打包后要放的地方(根目录下),filename是打包的文件名称(比如之前的main.js)。

image

为了方便直接定位到根目录,我们可以引入一个另外叫path的方法,从node中引进来,path下有一个resolve,里边有一个叫__dirname的参数(双下划线),它就代表根目录,我们可以通过这个方法直接定位到根目录下。
默认情况下webpack打包出来的文件夹叫dist,文件叫main.js。为了方便理解,我们这次在配置中自定义更改一下,设置打包文件夹叫newDist,文件叫newMain.js。

// 引入path
const path = require("path");

module.exports = {

  entry: "./src/index.js", // 入口文件

  output: {

    // 利用引入进来的path,定义到根目录。
    // 两个参数:__dirname:根目录;"./newDist" 跟目录下的文件夹名称
    path: path.resolve(__dirname, "./newDist"),
    filename: "newMain.js" // 打包后文件的名称

  }

}

然后,我们将之前打包的dist文件夹删除(一定要先删除,现在webpack不能帮我们删除旧的打包文件,防止重复,需要手动删除),重新执行打包,看一下效果。

image

这次打包新的版本,名称就变成了我们自定义设置的效果。这就是配置文件的厉害,可以随意的配置我们想要得到的东西。

3、src文件夹就是我们开发的文件夹,这个大家都知道。那么我们就可以在src中随意的创建文件。我们创建一个css文件,写点样式,然后在index.js中引入这个文件,再次打包一下:

image

在index.js根目录将它引入(因为webpack在默认情况下,只打包src下的index.js和跟它有关系的文件,想要把css也打包进来需要将css引入进来):

image

再次打包运行npm run dev,发现报错了:

image

报错原因是webpack不识别css。

注意:webpack默认支持js和json模块,其他都不支持!所想让它支持,需要安装对应的loader

这就明白了,loader是干啥的?就是让webpack不识别的,识别一下。

4、那就开始配置loader吧,loader的配置也是固定的,记住就好。loader是一个模块,所以需要写在 module里,loader它是一个规则,并且有很多,所以是用 rules:[] 数组的形式写,里边就可以写各种loader规则了。写规则的时候,两个常用的参数,一个是 test ,一个是 use :

// 引入path
const path = require("path");

module.exports = {

  entry: "./src/index.js", // 入口文件

  output: {

    // 利用引入进来的path,定义到根目录。
    // 两个参数:__dirname:根目录;"./dist" 文件夹名称
    path: path.resolve(__dirname, "./newDist"),
    filename: "newMain.js" // 打包后文件的名称

  },

  module: {
    rules: [{
      test: /\.css$/, // /\这里写要识别的后缀$/
      use: ["style-loader", "css-loader"] // css 需要这两个loader
    }]
  }

}

test后边是将要识别的后缀写在\后,$结束。use后是数组,需要的loader,就写在里边。这是规定。

现在运行会报错的,因为loader是插件,我们只引用了,可项目中并没有这两个插件,所以,我们需要下载进来,才能运行。

下载 style-loader和 css-loader:

npm i style-loader css-loader

下载完后再运行,看一下,没问题了,无报错信息。

有人可能会有疑问,你怎么知道需要这两个loader呢?这两个louder都是做什么的呢?为什么css会需要两个?

这个问题是这样的,用什么loader我也不知道,这些是在webpack官网中,会写明的,可以参考官网的文本,如果你需要什么到项目中,需要的loader都有什么。大家可以参考webpack官网。

loader的执行顺序是从右到左(去看代码),也就是先执行 css-loader,后执行style-loader。css-loader会将css文件解析成webpack所识别的文件,style-loader会将这个文件镶嵌到我们的html中(大概是这个意思)。

同样,我们引入一个图片也会报错,我们也需要按照这个方法,放进src一张图片,js引进来,写一个loader,图片需要file-loader,下载loader:

npm i file-loader

image

如图所示,loader中的use是可以写成对象的写法的。

我们把旧的打包文件删掉,然后重新运行,然后运行打包成功。我们看一下打包后的文件目录:

image

发现多了一些文件,其中有一个就是图片文件,这个图片的名字很长,其他打包的文件名字也很奇怪。这是因为我们图片的名字是webpack自动解析的,而其他的名字,我们在之前的filename中设置成了固定的了。
在loader中,有一个options属性,属性里可以设置打包后的name名称。出口文件的filename也可以写成"[name].js"的写法,改变名称。其他方法,可以参考官网设置,本次只讲常用的。仔细看代码,我们改变了出口的名字,和图片的名字:

// 引入path
const path = require("path")

module.exports = {
  entry: "./src/index.js", // 入口文件

  output: {
    // 利用引入进来的path,定义到根目录。
    // 两个参数:__dirname:根目录;"./dist" 文件夹名称
    path: path.resolve(__dirname, "./newDist"),
    filename: "[name].js" // 打包后文件的名称
  },

  module: {
    rules: [{
        test: /\.css$/, // /\这里写要识别的后缀$/
        use: ["style-loader", "css-loader"] // css 需要这两个loader
      },
      // 图片loader
      {
        test: /\.png$/,
        // use可以写成对象的写法
        use: {
          loader: "file-loader",
          options: {
            name: "[name].[ext]" // ext 在打包后,会生成对应的后缀名
          }
        }
      }
    ]
  }
}

删除之前打包文件,重新打包,打包后的文件名字就改变了:

image

其实这个时候,我们就可以写一个html文件放里了,然后在页面查看

我们刚才的css文件没有写全,可以在文件中,写个样式颜色:

image

然后再次重新打包。

5、写html文件,在打包中的文件里,可以放一个html文件,引入主文件的mian.js,然后可以放到网页中查看这个页面:

image

在文件夹中,可以双击html打开这个页面,我们就能看到页面变成了蓝色,控制台也有输出我们的数据:(没写图片标签,所以没有图片)

image

6、plugins的使用:

plugin是插件,可以帮助我们做一些事情,webpack插件真的是太多了,项目不同,我们用到的就不同,今天先讲两个常用的插件。既然是插件,那么这些插件功能,大神们已经给我们写好了,我们只需要下载后,引入进来,然后new一下使用就可以了。

clean-webpack-plugin插件:

这个插件有什么用呢,如果这篇文章你好好看的话,会发现我们刚才每次打包之前,都需要提前删除旧的文件包,否则就会把新的文件也打包在之前那里,这样就会有问题。所以我们每次打包前,就需要提前删除一下。但这样不光浪费时间,而且还很危险啊,如果一不小心删错了,把src文件删了,那不是傻眼了。所以大神们就开发了CleanWebpackPlugin插件,它能在我们运行打包命令的时候,自动的将之前旧的文件包删掉,然后再打包出新的文件(这不就是个宝贝吗),这就是插件的功能,那我们来尝试一下把:

首先先下载这个插件:

npm i clean-webpack-plugin --save-dev

然后引入进来:

image

怎么使用呢,刚才说了,写在plugins当中(插件不只是一个别忘了加s,复数!还得教你们英语,我太难了),我们只需要new一下就可以了,插件有很多,所以用数组的方式放进来就可以了。截取片段:

image

“不信邪的”(东北话:译为不相信的),自己再重新打包一下,是不是之前的会被删除,然后重新打包出新的文件。

再讲讲html-webpack-plugin插件:

我们刚才想看一下页面,是需要自己手动创建html文件的。
这个插件可以自动的将我们src文件下的html文件(一般项目必有这个文件),打包后自动放入我们的包中。
我们现在根目录下创建html文件
和刚才一样,我们尝试一下:

image

然后下载:

npm i html-webpack-plugin --save-dev

使用时可以设置三个参数:

title(打包后html文件下title标签中的标题名)

template(目标html文件,也就是根目录下的html页面路径)

filename(打包后的html名称)

plugins: [
    new CleanWebpackPlugin(),
    new htmlWebpackPlugin({
      title: "villin",
      template: "./index.html",
      filename: "villin.html"
    })
  ]

打包一下,会看到打包文件夹newDist下有了这个文件,并且仔细观察,这个插件还会自动的将我们需要的js引入进来。

image

这就是这两个插件的用法,其他插件,自己可以查阅官网。

------------ mode开发环境和生产环境: ----------

我们在打包时,会有自己的环境配置,开发环境development和生产环境production。

这两个有什么区别?在webpack打包时,这两个打包后的代码就有区别,开发环境下,打包出的代码是不压缩的,原因是便于我们开发人员在出错的时候,查找bug代码;生产环境下,代码会压缩成“自己爹都不认识了”。会去掉空格、回车、注释等,减少体积。我们可以看一下这两个环境。

1、我们可以设置环境,写上mode,后边跟上生产环境:(截取片段)

image

我们重新打包,打包成功后,看下打包后的main.js代码:

image

有兴趣的自己看到底,反正我是没兴趣……………………

2、我们再看一下开发环境下的打包代码:

更换环境mode: "development", // 开发环境

image

3、我们这样来回换环境,不如换个执行命令,我们还可以这样做,在创建一个js文件,里边写上不同的开发环境,然后再自定义一个执行命令,当我们想执行不同的配置时,只执行不同的命令即可。

新建一个文件,起名叫:webpack.config.pro.js
里边换一个环境:

image

自定义命令:这个命令执行的也是webpack,但是需要通过--config来告诉webpack,是哪个文件,所以在--config后边写上要执行的路径即可。我们刚才之前定义的叫dev,这次我们定一个叫build

image

这样我们再执行npm run build的时候,就可以打包成生产环境的代码了。两个不同的环境,只需要执行不同的命令即可。

------------ hash和chunkhash: ----------

为了提高每次加载时的资源速度,我们在项目开发时,就需要缓存,不变的需要缓存起来。所以就出来了hash值得问题,hash有三个,本次简单说说两个。

hash的使用,我们就在输出文件的name后边加上hash即可。

filename: "[name]_[hash].js"

这样就可以了,再次打包看一下,是不是打包后的名字发生了“蛇”一样的加长了,这就是hash,打包后,在使用时,就会将不变的文件进行缓存,每次加载时就不用了重复的加载。

但是这样看着名字太长了,我们可以设置名字后边乱码的的长度,在hash后边加上长度即可,比如,我就留5位数,那么这样写:

filename: "[name]_[hash:5].js"

再次打包,看一下名字长度,发生了变化。

但是这个hash在开发时,我们方便测试,可以使用。但是在发布时,要使用chunkhash,原因是,每次打包,即使仅仅一个文件更改,所有文件的名字都会重新更改。这样版本更新,用户可能在加载时,就要全部重新加载了。为了提高效率,我们换成chunkhash,这样针对性的的更新,更友好一下,使用方法和hash一样,只是名字换了。

当然除了输出文件可以用hash,其他名字也可以,比如loader,后边设置名字后,也可以使用hash。

以上就是webpack入门的简单使用,我们可以根据这些基本方法,查看自己公司的webpack配置 ,查看官网,深入的学习

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

分享:
开发与运维
使用钉钉扫一扫加入圈子
+ 订阅

集结各类场景实战经验,助你开发运维畅行无忧

其他文章