• webpack基础版及其常用插件分享超详细~~


    • webpack的作用
      1. 打包。把多个文件打成个数更小的文件。
      2. 支持模块化
      3. 优化: 代码压缩,加密
    • 掌握webpack的基本使用: 配置webpack.config.js

    • 基本使用 
      
      • 1
    • 入口

    • 出口

    • loader

      • 一切皆模块。不同文件用不同的loader来加载
    • plugin

      • 扩展功能
    • devServer

    webpack基本介绍

    webpack官网

    webpack是一个现代 JavaScript 应用程序的_静态模块打包器(module bundler)_

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GU1MfRsU-1656592134919)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/ce96419070204fbf8e2d5c5a2605cca2~tplv-k3u1fbpfcp-zoom-in-crop-mark:1956:0:0:0.image)]

    现代 javascript 应用程序的 静态模块打包器 (module bundler)

    • 静态: 文件资源
    • 模块: node环境, 引入文件, 遵守模块化语法

    除了合并代码, 还可以翻译压缩代码

    • less/sass -> css
    • ES6/7/8 -> ES5
    • html/css/js -> 压缩合并

    小结

    1. 什么是webpack?
    • 静态模块打包器
    • 还能翻译和压缩代码
    • 减小代码包体积, 让浏览器更快速打开网页

    学习webpack的准备工作

    准备

    环境准备:它是基于nodejs,所以本机一定要先安装了node。

    项目准备:webpack是用来对已有项目进行打包,所以一定是在某个项目下进行应用打包。

    知识准备:模块化(es6, commonjs模块化均可)

    操作顺序

    1. 安装node
    2. 用npm init 初始化项目(如果已经有package.json,则跳过这一步)
    3. 在当前项目中安装并使用webpack

    示例项目

    目标:在一个已存在的项目中,一个html文件中引入了两个js文件,完成某个功能。现在是的任务是把这两个js打包成一个js文件。

    操作步骤如下:

    初始化项目

    任意新建一个空文件夹,取名为webpack-demo,进入到文件夹内部,用 npm init -y 命令来生成一个package.json

    准备初始代码

    创建三个文件index.html,index.js,tool.js,最后的项目结构是:

    项目名
    ├── index.html
    ├── index.js
    ├── tool.js
    └── package.json 
    
    • 1
    • 2
    • 3
    • 4
    • 5

    拷贝如下素材:

    index.html

    <!DOCTYPE html>
    <html lang="zh">
    <head>
        <meta charset="UTF-8">
        <title>index</title>
      </head>
      <body>
        <div id="app">
          
        </div>
        <!-- 引入两个js文件 -->
        <script src="./tool.js"></script>
        <script src="./index.js"></script>
    
    </body>
    </html> 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    tool.js

    const updateDom = (id, content) =>{
        window.document.getElementById(id).innerHTML =  content
    } 
    
    • 1
    • 2
    • 3

    index.js

    updateDom ('app','index.html') 
    
    • 1

    说明:

    • 在一个html中引入多个js文件,并且要注意它们的顺序关系。
    • script代码在body的底部,这样可以确保是dom节点渲染在js代码执行之前。

    因为在index.js要用到tool.js的功能,所以还在index.html中同时引用了index.js和tool.js,并把tool.js的引用放在index.js的引用之前。如下整个代码的示意图:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-70EuOYqx-1656592134920)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/4635e2de74094cad957bb250ecd50fe4~tplv-k3u1fbpfcp-zoom-in-crop-mark:1956:0:0:0.image)]

    上面的代码中有如下问题:

    • js文件之间有先后的引用的关系:由于index.js中引用了tool.js的,所以必须要把tool.js放在index.js的前面。
    • 存在变量污染的情况:一个文件中定义的变量,在另一个文件中可能会被修改,覆盖。
    • 随着.js文件个数增加,则项目会越来越不好管理。

    解决思路:模块化 + webpack打包

    安装并使用webpack

    安装webpack

    webpack是一个工具,对于所有的项目都可以来使用,从这个意义上来讲,它是可以去全局安装的,但是,考虑到不同的项目中可能使用了不同的webpack版本,所以不推荐大家去全局安装。特别是打开一个老项目时,一定要注意一下它的webpack的版本号。

    前端很多悲惨故事,都是是从版本不一致开始的。

    采用局部安装的方式来安装它,注意,它只是一个开发依赖,并不是生产依赖,所以在命令行中加上-D。

    命令如下:npm i webpack webpack-cli -D // --save-dev

    下面来通过命令行工具来检查是否安装成功。

    # 方式一:
    node_modules.bin\webpack -v
    # 方式二:
    npx webpack -v 
    
    • 1
    • 2
    • 3
    • 4

    注意:

    • 由于webpack并不是全局安装的,所以并不能直接使用webpack -v来做检验。
    • npx是npm5.2之后提供的新功能。可以通过npx -v来检测它的版本。 在这里,我们通过它来调用项目安装的模块,它在运行时会在node_modules/.bin中去检查命令是否存在。

    webpack作为一个独立的工具,它与具体的项目无关。在你的项目中,通过开发依赖安装它。

    修改用模块化的方式来改写代码

    模块化的方式来修改:

    • 在tool.js中导出模块
    • 在index.js中使用模块

    在tool.js导出模块

    它用来提供一个方法,供其它模块来使用。这里使用commonjs规范(就是node.js中的导出模块的方式)导出工具方法。

    const updateDom = (id, content) =>{
        window.document.getElementById(id).innerHTML = content
    }
    + module.exports = {
    +  updateDom
    + } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在index.js中导入模块

    在index.js中引入tool.js中的定义的方法。注意,这里已经涉及到了在一个js中引用另一个js

    + const { updateDom } = require('./tool')
    updateDom ('app','index.html') 
    
    • 1
    • 2

    由于现在在index.js使用了require这种模块化的处理方式,所以它无法直接在浏览器中使用,如果直接在index.html中引用,浏览器会报错。

    我们接下来就需要使用webpack命令来对index.js进行处理了。

    使用webpack来做打包

    命令格式是:npx webpack 文件名

    这里的操作是:

    npx webpack ./index.js
    # 或者是
    node_modules/.bin/webpack index.js 
    
    • 1
    • 2
    • 3

    如果没有遇到错误,会看到类似的结果如下:

    $ npx webpack ./index.js
    Hash: b43d4771990a46286152
    Version: webpack 4.42.1
    Time: 101ms
    Built at: 2020-04-01 3:15:48 PM
      Asset      Size  Chunks             Chunk Names
    main.js  1.04 KiB       0  [emitted]  main
    Entrypoint main = main.js
    [0] ./index.js 71 bytes {0} [built]
    [1] ./tool.js 136 bytes {0} [built] 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    它说明打包操作已经成功:index.js和tool.js已经合成了一个main.js文件了。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zP25aQg4-1656592134920)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/3f6df7e002204f13894507e4e8dc1a3e~tplv-k3u1fbpfcp-zoom-in-crop-mark:1956:0:0:0.image)]

    webpack会分析入口文件中的引用关系,把相关的文件合成在一起,变成一个.js文件

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Cm1g3lSA-1656592134920)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/d97a970ba56b485d9a90bbd9fa2419c5~tplv-k3u1fbpfcp-zoom-in-crop-mark:1956:0:0:0.image)]

    示意如下:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EDhkFVmi-1656592134920)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/be41daee0cba4f5d8a754fa96cca86d6~tplv-k3u1fbpfcp-zoom-in-crop-mark:1956:0:0:0.image)]

    引入打包后的js

    把上面打包完成的main.js引入到index.html

    <!DOCTYPE html>
    <html lang="zh">
    
    <head>
      <meta charset="UTF-8">
      <title>index</title>
    </head>
    
    <body>
      <div id="app">
    
      </div>
      <!-- 引入打包后的.js文件 -->
        <script src="./dist/main.js"></script>
    </body>
    
    </html> 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    示意图如下:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WsfOnhMQ-1656592134921)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/c11b4ae129b0474ba8541f020c464f4e~tplv-k3u1fbpfcp-zoom-in-crop-mark:1956:0:0:0.image)]

    好的,现在你已经可以看到这个代码可以正常工作了吧。

    小结

    1. 为啥要用webpack?

      1. 有效处理模块化。默认情况下,浏览器并不支持模块化,而我们的前端项目又使用了模块化,有了webpack之后,就可以突破这个限制了。
      2. webpack可以把多个相互引用的.js文件打包成一个文件,且文件有加密,压缩的效果,上线更安全。
    2. 这个过程中nodejs起了什么作用?

      1. 它是webpack的运行基础,没有了nodejs环境,就无法做类似于文件读写的操作了。
      2. 最终生成的main.js并不是在nodejs环境中运行的,整个的项目效果还是在浏览器中运行的。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FVeJUn9Q-1656592134921)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/43ed0d0c6b4e4964ae15f038b8488cac~tplv-k3u1fbpfcp-zoom-in-crop-mark:1956:0:0:0.image)]

    认识webpack的配置文件

    了解配置文件

    工具运行的默认参数配置会放置在某个具体的文件。
    例如:迅雷/百度网盘下载的文件保存在哪里?

    配置文件的作用

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zlzwUBIX-1656592134921)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/8e8ec7c3c6424a9ab6edb226cb1d0879~tplv-k3u1fbpfcp-zoom-in-crop-mark:1956:0:0:0.image)]

    1. 是否特殊指定使用哪个配置文件?
      a. 是。找到这个指定的配置文件
      b. 否。去项目根目录找是否有一个名为webpack.config.js的文件。
      ⅰ. 找到。使用即可。
      ⅱ. 找不到。采用默认配置。

    创建并使用默认配置文件

    在项目根目录下创建一个名为webpack.config.js。其内容如下:

    module.exports = {
      mode: 'development', // 打包方式
    } 
    
    • 1
    • 2
    • 3

    这个文件的意义是导出一个配置项:用来对webpack的打包行为做设置。在操作层面,就是学习如何去使用这个文件。

    然后,再次运行打包命令,查看产生的main.js文件的内容,对比与之间的变化。

    小结

    1. webpack的默认配置文件的名字是?
    2. 配置文件的作用是?

    设置入口和出口

    在配置文件中,配置自定义的入口和出口

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-A0A0NvYB-1656592134922)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/2acadfdf04764e4f9a3e320cf2e03120~tplv-k3u1fbpfcp-zoom-in-crop-mark:1956:0:0:0.image)]

    入口和出口

    入口文件: 指定了webpack从哪个文件开始工作。在它的内部会引入其他的模块,这样在打包时就会「顺藤摸瓜」也将其他的文件打包进来。

    出口文件:指定了最后打包之后的文件,重点是这个文件的具体位置。

    在webpack中,默认的入口和出口分别是:

    • 默认入口是:./src/index.js
    • 默认出口是:./dist/main.js。

    也就是说,如果直接在根目录下运行webpack,它会直接去找.src下的index.js,并把打包之后的代码放在dist/main.js下。

    了解默认入口文件

    修改目录结构,新建一个src目录,并把index.js,tool.js,tooles6.js移动到它下面。

    项目名
    ├── index.html
    ├── src
    │   ├── index.js
    │   └── tool.js
    └── package.json 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    直接省略入口文件,直接打包: npx webpack 由于在src目录已经存在index.js

    再来测试一下。

    设置入口文件

    需求:如果在实际开发中,希望:

    • 这个入口文件不是index.js,而是main.js
    • 整体js文件不是放在src目录下,而是src/js下。

    解决:

    (1) 调整目录结构如下:

    项目名
    ├── index.html
    ├── src
    │   └── js
    │       ├── main.js
    │       └── tool.js
    ├── webpack.config.js  # webpack的配置文件
    └── package.json 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    (2) 然后,修改配置项

    1. 修改src/index.js的名字为src/js/main.js
    2. 在webpack.config.js的配置项中添加 entry
    module.exports = {
      mode: 'development', // 打包方式
      entry:'./src/js/main.js' // 入口文件
    } 
    
    • 1
    • 2
    • 3
    • 4
    1. 重新打包,测试。

    指定出口文件

    在webpack.config.js中设置output项。

    目标: 把出口文件设置为在build目录下的bundle.js

    // 引入nodejs中的核心模块
    const path = require('path') 
    console.log(path.join(__dirname,'/build'))
    module.exports = {
        mode: "production",
        entry: './src/js/main.js', // 入口文件
        output: {
            "path": path.join(__dirname,'/build'), // 决定出口文件在哪里
            "filename": "bundle.js" // 设置出口文件的名字。默认情况下,它叫main.js
        }
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    说明:

    • output中的filename用来指定打包后的文件名字。
    • output中的path用来指定打包后的路径。注意:它必须是绝对路径。所以,这里引用path模块中的join和__dirname来生成绝对路径。
    • 如果path中的路径不存在,它会自动创建。

    修改打包模式

    webpack.config.js中的mode项用来设置打包的方式,如果不设置,会默认为production。

    module.exports = {
      mode:"development"
    } 
    
    • 1
    • 2
    • 3

    webpack给mode 提供了两个模式:

    ● development :开发模式(代码不会压缩 混淆)
    ● production:生产模式(压缩,混淆,加密… 不可读)

    在打包时指定配置文件

    下面,自已创建一个webpack.dev.js的文件,用它来做配置文件。

    在项目根目录下创建webpack.dev.js,内容如下:

    module.exports = {
      output:{
        filename:'boundle.js'
      }
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5

    下面,希望使用这个配置文件中的设置来打包。

    它的格式是:

    npx webpack --config webpack的配置文件

    运行命令:

    npx webpack --config webpack.dev.js

    简化打包命令

    背景

    当涉及多个打包配置要指定时,打包命令比比较复杂,难以记忆。

    定制script

    可以在package.json中添加script命令来快速启动webpack,格式如下:

    “scripts”: {
    “自定义命令名”: “要具体执行的代码”,
    }

    示例

    "scripts": {
      "dev": "webpack --config webpack.dev.js",
      "build": "webpack",
      "test": "echo "Error: no test specified" && exit 1"
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5

    注意:在script中不再需要添加npx。它会自动在node_modules/.bin中去找命令。

    这样 ,我们就得到了两个可以执行的命令: dev, build 。

    可以在根目录下的小黑窗中通过:

    npm run build, npm run dev 来运行

    webpack基础使用阶段小结

    • webpack的配置文件默认名是webpack.config.js,也可以单独指定
    • 学习webpack就学习webpack.config.js的使用。
    • 把webpack的命令集成到script中可以简化打包命令。
    • 可以自行定义入口和出口文件

    loader整体介绍

    在webpack看来 一切皆模块,图片,样式文件,js文件… 。 但是webpack默认只能处理js模块,对于非js的内容,例如css, less文件,图片文件等等 它就需要一些帮手来处理了。这些帮手就是loader

    webpack 可以使用 loader 来预处理文件。这允许你打包除 JavaScript 之外的任何静态资源。你可以使用 Node.js 来很简单地编写自己的 loader。

    loader处理css文件

    如何引入css文件呢?

    传统开发中:css样式是通过在.html文件中通过link标签引入的。但是,现代开发中,我们会把css文件看做资源,直接在.js文件中导入。

    下面,我们来具体讨论如何处理.css文件。

    创建.css文件

    项目名
    ├── index.html
    ├── src
    │   ├── css
    │   │   ├── public.css
    │   │   └── style.css
    │   └── js
    │       ├── main.js
    │       ├── tool.js
    │       └── tooles6.js
    └── package.json 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    src/css/public.css的内容如下

    body,html{
      padding:0;
      font-size:14px;
    } 
    
    • 1
    • 2
    • 3
    • 4

    src/css/style.css的内容如下

    @import "public.css";
    div {
      border:4px solid #ccc;
      width: 50%;
      height: 200px;
      margin:30px auto;
      box-shadow: 3px 3px 3px #ccc;
      background-color: #fff;
      text-align: center;
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    说明:css的@import语句用来导入另一个css文件。

    在.js中导入css

    在js文件中引入css,就像vue项目中引入第三方ui样式一样,如element-ui的使用说明中提到的:

    import Vue from 'vue';
    import ElementUI from 'element-ui';
    // 引入 css
    import 'element-ui/lib/theme-chalk/index.css';
    import App from './App.vue';
    
    Vue.use(ElementUI);
    
    new Vue({
      el: '#app',
      render: h => h(App)
    }); 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    很明显,上面的.js代码中引入了.css。

    下面,我们修改自已的main.js,在 src/js/main.js中,引入css。

    // nodejs中的模块化
    const { updateDom } = require('./tool')
    // es6中的模块化
    import {log} from './tooles6'
    
    + import '../css/style.css'
    updateDom ('app','index.html')
    log('test') 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    再次,打包代码,会报错,具体的保存信息如下:

    ERROR in ./src/css/style.css 1:0
    Module parse failed: Unexpected character '@' (1:0)
    You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
    > @import "public.css";
    | div {
    |   padding:20px;
     @ ./src/js/main.js 4:0-26 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    上面报错的原因是:webpack把.css文件内容当作了js代码来运行,那当然会报错了。所以,解决方法是安装相应的loader来处理。

    安装并使用css-loader

    对于loader的使用,其基本步骤是一致的,分成两步:

    1. 安装npm包

    2. 配置webpack.config.js中的module

    安装

    安装包的命令是:npm i css-loader -D 。它也是开发依赖。

    在配置文件中使用

    修改webpack.config.js文件,添加module

    const path = require('path')
    module.exports = {
      mode: 'development',
      entry:'./src/js/main.js',
      output:{
        path:path.resolve(__dirname, './build'),
        filename:'bundle.js'
      },
    +  module:{ // 处理非js模块
    +    rules:[ // 规则
    +      {
    +        test: /.css$/, 		// 正则测试
    +        use: ['css-loader'] 	// loader
    +      }
    +    ]
    +  }
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    再次打包

    它不会报错。但是,页面上也并没有出现样式的效果。打包之后的文件中并没有包含css代码。

    安装并使用style-loader

    如果我们希望样式生效,最终在.html文件中有两种情况:

    • 有style标签
    • 有link标签

    而css-loader只是能让你在.js中通过import来引入.css,如果你希望引入的css代码最终以style标签的方式插入到html页面中,则还需要安装一个loader:style-loader

    安装

    npm i style-loader -D

    配置

    const path = require('path')
    module.exports = {
      mode: 'development',
      entry:'./src/js/main.js',
      output:{
        publicPath:'https://www.baidu.com',
        path:path.resolve(__dirname, './build'),
        filename:'bundle.js'
      },
      module:{ // 处理非js模块
        rules:[ // 规则
          {
            test: /.css$/, 		// 正则测试
            use: ['style-loader','css-loader'] 	// loader
          }
        ]
      }
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    Tip: 在有多个loader的情况下,use数组中的loader执行顺序是从右到左的过程。即:

    • 先用css-loader来处理css
    • 再用style-loader把css代码插入到html中的style标签中。

    打包查看效果

    现在就能看到css的效果了 。

    小结

    1. 为什么要在.js中引入css?而不直接在.html中引入css文件?

    loader处理less文件

    如果希望处理less文件,则还需要去安装额外的包。

    创建less文件

    在src目录的less目录下创建 index.less,

    项目名
    ├── index.html
    ├── src
    │   ├── less
    │   │   └── index.less
    │   ├── css
    │   │   ├── public.css
    │   │   └── style.css
    │   └── js
    │       ├── main.js
    │       ├── tool.js
    │       └── tooles6.js
    └── package.json 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    则内容如下:

    @import "../css/style.css";
    
    body{
      div {
        color: red;
      }
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在.js中引用.less

    在src/js/main.js文件中引入less

    // nodejs中的模块化
    const { updateDom } = require('./tool')
    // es6中的模块化
    import {log} from './tooles6'
    
    - import '../css/style.css'
    + import '../less/index.less'
    updateDom ('app','index.html')
    log('test') 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    安装包

    参考官网

    npm i less-loader less -D
    -------------------------
    + less@3.11.2
    + less-loader@6.1.0
    added 50 packages from 123 contributors in 23.883s 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • less 用来把less–>css
    • less-loader用来加载less文件。

    配置模块

    在rules中添加一个配置,专门针对less文件。

    module.exports = {
        // 非js模块,在这里处理
        module: {
            rules: [ // 规则
                {
                    test: /.css$/,     // 正则匹配,以.css结尾的文件
                    // 如果发现是.css文件,则由如下两个loader来处理
                    // 处理的顺序是   从右向左
                    // css-loader: 作用是允许.js中引入.css
                    // style-loader:作用是在.html上创建style标签,把css代码输入进去
    
                    use: ['style-loader','css-loader'] // 匹配成功,使用指定的loader
                },
    +            {
    +                 test: /.less$/,     // 正则匹配,以.less结尾的文件
                    // 如果发现是.less文件,则由如下三个loader来处理
                    // 处理的顺序是   从右向左
                    // less-loader: 作用是加载less文件,会帮你less转成css
                    // css-loader: 作用是允许.js中引入.css
                    // style-loader:作用是在.html上创建style标签,把css代码输入进去
                    
     +                use: ['style-loader','css-loader','less-loader'] // 匹配成功,使用指定的loader
    +             }
            ]
        }
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    注意:如上配置中,对于less文件的处理涉及三个loader,其处理顺序是less-loader --> css-loader–>style-loader。

    • less-loader:用来加载less文件,并处理成css
    • css-loader:用来加载css文件
    • style-loader:用来将css代码以style标签的格式插入到html文件中

    处理资源文件

    目标:处理资源文件。假设在css中引入图片,要怎么处理呢?

    在项目中引入图片

    在src下新增目录,img,并在其下放置两张图片。注意:一张图片大一些,一张图片小一些(可以自行决定)。

      • webpack.png: 49.4kb
      • webpack.svg: 3kb
    项目名
    ├── index.html
    ├── src
    │   ├── less
    │   │   └── index.less
    │   ├── img
    │   │   ├── webpack.png
    │   │   └── webpack.svg
    │   ├── css
    │   │   ├── public.css
    │   │   └── style.css
    │   └── js
    │       ├── main.js
    │       ├── tool.js
    │       └── tooles6.js
    └── package.json 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    使用图片

    两种方式使用图片:

    • 作为css的背景图
    • 作为独立的图片资源使用

    在style.css中引入图片,作为div标签的background。

    @import "public.css";
    div {
      border:4px solid #ccc;
      width: 50%;
      height: 200px;
      margin:30px auto;
      box-shadow: 3px 3px 3px #ccc;
      background-color:pink;
      text-align: center;
    +  background-image: url('../img/webpack.svg')
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    在src/main.js中,通过代码 - 把大图插入到创建的img标签上, 添加body上显示

    // 引入图片-使用
    import imgUrl from '../img/webpack.png'
    const theImg = document.createElement("img")
    theImg.src = imgUrl
    document.body.appendChild(theImg) 
    
    • 1
    • 2
    • 3
    • 4
    • 5

    配置

    webpack5内置处理方案, 只需要填入配置即可 参考:asset module资源模块文档

    webpack.config.js中的内容如下

    module: {
        rules: [ 
            // ...省略其他
            {
                test: /.(png|jpg|gif|jpeg)$/i, // 匹配图片文件
                type: 'asset' // 在导出一个 data URI 和一个单独的文件之间自动选择
            }
        ]
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    1. 打包后运行dist/index.html观察区别

    loader小结

    • 一切皆模块,不同的模块有不同的loader

    • loader

      • 第一步:安装包
      • 第二步:配置rules

    plugin整体说明

    webpack中除了loader之外,还有一个核心概念:plugin,中文就是插件。它可以用来增强webpack的功能。

    plugin是用于扩展webpack的功能,各种各样的plugin几乎可以让webpack做任何与构建相关关的事情。
    plugin的配置很简单,plugins配置项接收一个数组,数组里的每一项都是一个要使用的plugin的实例,plugin需要的参数通过构造函数传入。

    使用plugin的难点在于plugin本身的配置项,而不是如何在webpack中引入plugin,几乎所有webpack无法直接实现的功能,都能找到开源的plugin去解决,我们要做的就是去找更据自己的需要找出相应的plugin。

    html-webpack-plugin

    功能:把我们自已写的.html文件复制到指定打包出口目录下,并引入相关的资源代码。

    为html文件中引入的外部资源如script、link动态添加每次compile后的hash,防止引用缓存的外部文件问题。可以生成创建html入口文件。

    官网:www.npmjs.com/package/htm…

    实现步骤:

    下载安装

    命令:npm i html-webpack-plugin -D

    配置

    在webpack.config.js中,做两件事:

    1. 引入插件
    const HtmlWebpackPlugin = require('html-webpack-plugin'); 
    
    • 1
    1. 添加一个plugins配置
    const HtmlWebpackPlugin = require('html-webpack-plugin');
    // 引入nodejs中的核心模块
    const path = require('path') 
    console.log(path.join(__dirname,'/build'))
    module.exports = {
        mode: "production",
        entry: './src/js/main.js', // 入口文件
        output: {
            path: path.join(__dirname,'/build'),
            filename: "bundle.js" // 设置出口文件的名字。默认情况下,它叫main.js
        },
        // 非js模块,在这里处理
        module: {
            rules: [ // 规则
                {
                    test: /.css$/,     // 正则匹配,以.css结尾的文件
                    // 如果发现是.css文件,则由如下两个loader来处理
                    // 处理的顺序是   从右向左
                    // css-loader: 作用是允许.js中引入.css
                    // style-loader:作用是在.html上创建style标签,把css代码输入进去
    
                    use: ['style-loader','css-loader'] // 匹配成功,使用指定的loader
                },
                {
                    test: /.less$/,     // 正则匹配,以.less结尾的文件
                    // 如果发现是.less文件,则由如下三个loader来处理
                    // 处理的顺序是   从右向左
                    // less-loader: 作用是加载less文件,会帮你less转成css
                    // css-loader: 作用是允许.js中引入.css
                    // style-loader:作用是在.html上创建style标签,把css代码输入进去
                    
                    // use: ['style-loader','css-loader','less-loader'] // 匹配成功,使用指定的loader
                    // MiniCssExtractPlugin.loader :把css放在文件中而不是style中
                    use: [{loader: MiniCssExtractPlugin.loader},'css-loader','less-loader']
                    
                },
                {
                    test:/.(png|svg)$/,// 正则匹配,以.png结尾的文件, 以.svg结尾的文件
                    // use:['url-loader'] // 匹配成功,使用指定的loader
                    use: [
                        {
                            loader:'url-loader',
                            options:{
                                limit: 3 * 1024 // 限制大小为3k
                            }
                        }
                    ]
                }
            ]
        },
        plugins: [
            new HtmlWebpackPlugin({ // 打包输出HTML
                minify: { // 压缩HTML文件
                  removeComments: true, // 移除HTML中的注释
                  collapseWhitespace: true, // 删除空白符与换行符
                  minifyCSS: true// 压缩内联css
                },
                filename: 'index.html',
                template: path.resolve('./index.html') // 指定模块的位置
              })
        ]
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    1. 打包测试
    • 它会把template中指定的.html文件复制(压缩)到出口文件夹
    • 还会自动附上打包之后.css和 .js代码

    clean-webpack-plugin

    在生成打包文件之前,把目录清空掉。

    安装

    npm i clean-webpack-plugin -D

    修改配置文件

    1. 引入:
    const { CleanWebpackPlugin } = require('clean-webpack-plugin') 
    
    • 1
    1. 添加plugins
    plugins:[
            new CleanWebpackPlugin(),
            其它...
    ] 
    
    • 1
    • 2
    • 3
    • 4

    plugin小结

    plugin用来增加webpack能力。

    步骤:

    1. 下载安装

    2. 配置webpack.config.js

      1. 引入
      2. 添加plugins的设置

    webpack实时打包

    目标

    实现实时打包预览效果。当我们修改了代码时,立即运行打包命令,并显示效果。

    工具:[webpack-dev-server]

    注意

    • 项目开发都是对src目录内部的文件进行更新,不要去修改dist打包好的文件
    • 现在对src内部的任何文件做修改操作后,都需要重新打包,才可以看到对应效果

    步骤

    1. 安装
    npm i webpack-dev-server  -D
    -------------------------------
    + webpack-dev-server@3.11.0
    added 395 packages from 272 contributors in 62.727s 
    
    • 1
    • 2
    • 3
    • 4
    1. 在webpack.config.js中做如下配置
    module.exports = {
        // 其他省略....
      
        // 配置 webpack-dev-server的选项
        devServer: {
            host: '127.0.0.1',  // 配置启动ip地址
            port: 10088,  // 配置端口
            open: true  // 配置是否自动打开浏览器
        }
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    1. 在package.json中补充一个script
    "scripts": {
    +    "dev": "webpack-dev-server",  
       // 它默认会找webpack.config.js文件
       
       "build": "webpack-dev-server --config  webpack.config.js" 
        // 指定使用webpack.config.js配置文件文件
    }, 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    1. 启动命令
      现在通过 npm run dev就可以实现 实时打包、实时编译、实时浏览器查看效果了。它会自动打开一个浏览器窗口。
    2. 测试
      • 修改.js代码,
      • 修改.css代码,检查是否会重启

    注意:

    浏览器看到的实时效果是服务器通过“内存”提供的,没有物理文件,也不会生成dist目录

    拓展:babel-loader

    能够把es6高级内容变为es5的loader名称为 babel-loader

    es6/es7/es8等等高级标准有很多(let、箭头函数、对象解构赋值、…展开运算符、反勾号字符串等等),每个标准都需要一个独立的plugin进行降级处理,如果使用许多高级标准内容,那么势必要为此安装许多plugin,这样工作比较繁琐,系统已经考虑到这点了,其通过preset把许多常用的plugin给做了集合,因此一般性的使用只需要安装preset即可搞定(如果项目应用到了一个生僻的高级标准内容,preset处理不来,就还需要再安装对应的plugin处理)

    let----降级---->plugin

    箭头函数----降级—>plugin

    npm官网: babel-loader

    babel官网:www.babeljs.cn/setup#insta…

    步骤:

    1. 安装依赖包
    npm i babel-loader @babel/core @babel/preset-env -D 
    
    • 1
    1. 在webpack.config.js中做如下配置:
    {
        test: /.js$/,
            exclude: /node_modules/,  // 排除目录
            use: [
                    {
                        loader:'babel-loader',
                     	options: {
                            presets: ['@babel/preset-env']
                        }
                    }
            ]  // es6转es5
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    说明: @babel/preset-env用来指定按什么样的预设来进行降级处理

    1. 打包测试
      打包之后,去打包后的文件中检查是否已经把const和箭头函数这种es6的代码转成了es5的代码。

    拓展:source map的说明

    目标: source map概念, 用于在浏览器调试错误使用, 记录代码打包前原始位置

    1. 准备: src/main.js产生一个未定义变量的报错, 启动webpack服务器
    console.log(abc); // 不要声明abc变量 
    
    • 1
    1. 问题: 看浏览器-控制台报错信息, 但是_发现看不出哪行代码报错了_
      原因: webpack对代码, 压缩, 混淆, 减小文件的体积(提高文件的加载效率)
      • 变量被替换成没有任何语义的名称
      • 空行和注释被剔除, 压缩到一行

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mZyBbJLe-1656592134922)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/24d441beb8c24878b065f4ad0bd2ade0~tplv-k3u1fbpfcp-zoom-in-crop-mark:1956:0:0:0.image)]

    解决方案: 启用source map

    开发环境

    1. webpack.config.js - 配置
    module.exports = {
      // ...其他配置
      mode: 'development', 
      // 开发模式 是development
      // webpack内部不会使用内置优化, 不压缩代码
      // 使用'production'上线生产模式, 会压缩代码
      
    +  devtool: 'cheap-module-source-map', 
      // cheap-module-source-map 开发模式下使用, 保证运行时的行数 和 源代码行数 一致  (默认不写是eval模式)
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    1. 重新启动开发服务器/打包, 观察是否有错误代码打包前的位置信息了

    生产环境

    1. 不显示源码, 但是可以看到哪行报错
    devtool: 'nosources-source-map' 
    
    • 1

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6myfajkA-1656592134922)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/2374d06349bc4dc1859fd956b959a6a0~tplv-k3u1fbpfcp-zoom-in-crop-mark:1956:0:0:0.image)]

    1. 显示源码
    devtool: 'source-map' 
    
    • 1

    \

    devtool值说明

    规则字符串列表:webpack.docschina.org/configurati…

    格式: [inline-|hidden-|eval-][nosources-][cheap-[module-]]source-map (了解即可)

    规则值速度位置说明
    false建立:最快 重建:最快不开启sourcemap(规则值写错也是这个)
    inline建立:最慢 重建:最慢内嵌报错信息, 以及源码和源码位置信息
    hidden建立:最慢 重建:最慢独立map文件报错信息, 没有源码和源码位置信息
    eval建立:快 重建:最快内嵌报错信息, 以及源码 (mode为development时使用这个值)
    cheap建立:固定 重建:慢独立map文件报错信息, 以及源码和源码的行数(没有列)
    module建立:慢 重建:快速与别的一起用是否为loaders加载器生成source map
    [xxx-…]source-map建立:最慢 重建:最慢独立map文件报错信息, 以及源码和源码位置信息
    nosource建立:最慢 重建:最慢独立map文件报错信息, 不显示源码

    总结: 名字如何组合, 还要看上面文档, 不记录 快于 内嵌 快于 独立文件

    devtool常用组合

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MJUlz33v-1656592134923)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/59e6c2ff314c42ecbb359a828bcfbdd8~tplv-k3u1fbpfcp-zoom-in-crop-mark:1956:0:0:0.image)]

    拓展:使用es6模块化

    webpack中也是支持es6模块化的。

    新建tooles6.js文件,内容如下:

    const log = (content) => {
      console.log(Date.now(),content)
    }
    
    // es6 的导入
    export { log } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    注意,这里采用的是es6中的模块化导出。

    接下来,在index.js中引入,并使用这个模块

    // nodejs中的模块化
    const { updateDom } = require('./tool')
    // es6中的模块化
    import {log} from './tooles6'
    
    updateDom ('app','index.html')
    log('test') 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    最后,打包 index.js ,在index.html中测试。

    它可以处理es6的模块化和nodejs中的模块化。

    总结webpack(前端工程化)常见问答

    1、什么是webpack

    1. webpack是一个javascript的静态模块打包工具
    2. webpack里一切文件皆模块,通过loader转换文件,通过plugin注入钩子,增强功能
    3. 最后输出由多个模块组合成的文件,webpack专注构建模块化项目

    2、webpack的优点是什么?

    1. 专注于处理模块化的项目,能做到开箱即用,一步到位
    2. 通过plugin扩展,完整好用又不失灵活
    3. 通过loaders扩展, 可以让webpack把所有类型的文件都解析打包
    4. 社区庞大活跃,经常引入紧跟时代发展的新特性,能为大多数场景找到已有的开源扩展

    3、webpack的构建流程是什么?从读取配置到输出文件这个过程尽量说全

    webpack 的运行流程是一个串行的过程,从启动到结束会依次执行以下流程:

    1. 初始化参数:从配置文件读取与合并参数,得出最终的参数
    2. 开始编译:用上一步得到的参数初始化 Compiler 对象,加载所有配置的插件,开始执行编译
    3. 确定入口:根据配置中的 entry 找出所有的入口文件
    4. 编译模块:从入口文件出发,调用所有配置的 Loader 对模块进行翻译,再找出该模块依赖的模块,再递归本步骤直到所有入口依赖的文件都经过了本步骤的处理
    5. 完成模块编译:在经过第4步使用 Loader 翻译完所有模块后,得到了每个模块被翻译后的最终内容以及它们之间的依赖关系
    6. 输出资源:根据入口和模块之间的依赖关系,组装成一个个包含多个模块的 Chunk,再把每个 Chunk 转换成一个单独的文件加入到输出列表,这步是可以修改输出内容的最后机会
    7. 输出完成:在确定好输出内容后,根据配置确定输出的路径和文件名,把文件内容写入到文件系统。

    在以上过程中,webpack 会在特定的时间点广播出特定的事件,插件在监听到感兴趣的事件后会执行特定的逻辑,并且插件可以调用 webpack 提供的 API 改变 webpack 的运行结果

    4、说一下 webpack 的热更新原理(必会)

    webpack 的热更新又称热替换(Hot Module Replacement),缩写为 HMR。这个机制可以做到不用刷新浏览器而将新变更的模块替换掉旧的模块。

    HMR的核心就是客户端从服务端拉去更新后的文件,准确的说是 chunk diff (chunk 需要更新的部分),实际上 WDS(webpack-dev-server) 与浏览器之间维护了一个 Websocket,当本地资源发生变化时,WDS 会向浏览器推送更新,并带上构建时的 hash,让客户端与上一次资源进行对比。客户端对比出差异后会向 WDS 发请求来获取更改内容(文件列表、hash),这样客户端就可以再借助这些信息继续向 WDS 发起 jsonp 请求获取该chunk的增量更新。

    后续的部分(拿到增量更新之后如何处理?哪些状态该保留?哪些又需要更新?)由 HotModulePlugin 来完成,提供了相关 API 以供开发者针对自身场景进行处理,像react-hot-loader 和 vue-loader 都是借助这些 API 实现 HMR。

    5、有哪些常见的Loader?他们是解决什么问题的?(必会)

    1、 file-loader:把文件输出到一个文件夹中,在代码中通过相对 URL 去引用输出的文件

    2、 url-loader:和 file-loader 类似,但是能在文件很小的情况下以 base64 的方式把文件内容注入到代码中去

    3、 source-map-loader:加载额外的 Source Map 文件,以方便断点调试

    4、 image-loader:加载并且压缩图片文件

    5、 babel-loader:把 ES6 转换成 ES5

    6、 css-loader:加载 CSS,支持模块化、压缩、文件导入等特性

    7、 style-loader:把 CSS 代码注入到 JavaScript 中,通过 DOM 操作去加载 CSS。

    8、 eslint-loader:通过 ESLint 检查 JavaScript 代码

    6、Loader和Plugin的不同?

    1) 不同的作用

    loader直译为"加载器"。webpack将一切文件视为模块,但是webpack原生是只能解析js文件,如果想将其他文件也打包的话,就会用到loader。 所以loader的作用是让webpack拥有了加载和解析非JavaScript文件的能力。

    Plugin直译为"插件"。Plugin可以扩展webpack的功能,让webpack具有更多的灵活性。 在 webpack 运行的生命周期中会广播出许多事件,Plugin 可以监听这些事件,在合适的时机通过 webpack 提供的 API 改变输出结果。

    2) 不同的用法

    Loader在module.rules中配置,也就是说他作为模块的解析规则而存在。 类型为数组,每一项都是一个Object,里面描述了对于什么类型的文件(test),使用什么加载(loader)和使用的参数(options)

    Plugin在plugins中单独配置。 类型为数组,每一项是一个plugin的实例,参数都通过构造函数传入。

  • 相关阅读:
    【Cherno的C++视频】Continuous integration in C++
    数据结构-顺序表及其应用
    JMeter 常见函数讲解
    Flask像Jenkins一样构建自动化测试任务
    Visual Studio运用Entity Framework连接数据库
    JavaScript协程(function*/yield)转化为异步(async/await)
    [线程与网络] 网络编程与通信原理(五): 深入理解网络层IP协议与数据链路层以太网协议
    yolox小计
    vue3后台管理框架之技术栈
    【Linux】centos 7.2 max user processes修改不生效
  • 原文地址:https://blog.csdn.net/web22050702/article/details/125547755