本文基于:峰华前端工程师--30分钟掌握Webpack

为什么使用 Webpack

在我们进行传统网页开发中,会在 index.html 中引入大量的 jscss 文件,不仅可能会导致命名冲突,还会使页面体积变大,因为如果引用了第三方库,需要加载所有的代码。而在 node.js 出现后,javascript 项目支持通过 require 支持模块化开发了,并且支出 npm 方便地管理依赖。

借着 node.js 和浏览器js 的一致性,前端项目开始在 node.js 下开发,完成之后把代码构建成浏览器支持的形式。对于 reactvue 这种组件化的开发方式,因为有很多分散的文件,那么久特别需要这样的构建操作。

Webpack 就是进行这一步构建操作的,把 node.js 模块化的代码转化为浏览器可执行的代码。它提供了 importexport ES6模块化语法的支持,然后通过分析代码中 import 导入的依赖,把需要的代码加载进来。在 Webpack 中,任何文件都可以通过 import 导入,只要有对应的 loader 就可以了。在打包过程中,还可以通过插件来干预打包过程,例如剔除不必要的代码,形成体积更小的项目。

创建项目

  • 打开命令行工具,我们在这里创建一个名为 blog 的博客项目:

    mkdir blog
    cd blog
    yarn init -y
    (或者npm init)
  • 添加 webpack 依赖:

    yarn add webpack webpack-cli --dev
  • 使用 VSCode 打开项目:

    code .

初出茅庐

  • blog 项目下新建 src 文件下,创建 index.js

    console.log("Hello World");

    我们先只做一个简单的输出.

  • blog 项目下新建 index.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    </head>
    <body>
    <h1>Hello World</h1>
    <script src="./dist/index.js"></script>
    </body>
    </html>
  • 使用 LiveServer 查看刚刚所编写的 html页面:

    可以看到浏览器成功显示了 "Hello World",并且控制台也能够成功输出.

  • 尝试使用 webpack 打包

    打开控制台,输入 npx webpack

npx 能够直接运行 node_modules 下面安装的库的自带的命令行,而不用写 node_modules 下一串的绝对路径。

打包完成后可以看到项目里面生成了一个 dist 目录,里面有一个 main.js 文件,其内部的内容和我们刚刚所编写的 index.js 的文件一模一样,这是因为我们并没有使用任何 import 来导入其他的依赖。

使用 import 导入依赖

  • src 下新建一个 data.js 文件:

    export function getBlogPosts() {
    return ["博客1", "博客2", "博客3"];
    }
  • index.js 中导入 data.js 中的函数并调用:

    import { getBlogPosts } from "./data";
    
    console.log(getBlogPosts());
  • 重新使用 webpack 打包以下,查看结果:

    npx webpack

    现在进入 /dist/main.js 中看一下,代码被简化成了直接输出刚才我们所编写的数组的语句,说明 webpack 自动判断了我们所编写代码的逻辑,并通过 import 语句得到了我们所引入的代码,分析后生成新的 js 文件.

  • 在网页中查看下结果:

    成功地输出了数组.

Webpack 配置文件

webpack 的配置文件可以说是 webpack 最核心的部分了,我们可以在配置文件中修改入口和出口文件、通过 loader 加载不同类型的文件和使用 plugins 对代码做其他的操作。

尝试修改打包后生成文件的名称

  • 在项目中新建 webpack.config.js 文件:

    const path = require("path");
    
    module.export = {
    mode: "development",
    // 设置为开发模式,方便调试
    entry: "./src/index.js",
    output: {
    filename: "dist.js",
    path: path.resolve(__dirname, "dist"),
    // 设置文件名和目录
    }
    }
  • 执行 npx webpack 命令打包

    可以看到 dist 文件夹下多了个 dist.js 文件.

使用模块化语法

  • 修改 /index.htmlscript 标签:

    <script src="./dist/dist.js"></script>

    main.js 修改成为我们刚刚使用 webpack 打包生成的 dist.js

  • 修改 /src/index.js 文件,将之前编写的数组变成 ul 元素插入页面中:

    const blogs = getBlogPosts();
    
    const ul = document.createElement("ul");
    blogs.forEach(blog => {
    const li = document.createElement("li");
    li.innerText = blog;
    ul.appendChild(li);
    }) document.body.appendChild(ul);
  • npx webpack

    列表成功插入到了页面.

引入 css

  • src 下新建 style.css 文件:

    h1 {
    color: blueviolet;
    }

    这里只是简单地改变 h1 标签的颜色.

  • /src/index.js 中引入 css 文件:

    import "./style.css";
  • 安装 loader

    打开控制台,输入:

    yarn add --dev style-loader css-loader
  • webpack.config.js 中配置 loader

    module.exports = {
    mode: "development",
    output: {...},
    ... module: {
    rules: [{
    test: /\.css$/i,
    use: ["style-loader", "css-loader"],
    }]
    }
    }

    module -> rules -> test 内是一个正则表达式,表示以 .css 结尾的文件.

    use 属性下是所使用的 loader

  • 再次使用 npx webpack 打包:

    可以看到,刚才写的样式生效了.

加载图片

  • webpack 原生支持图片等静态文件,但是需要在 webpack.config.js 中编写配置:

    module.exports = {
    ...
    module: {
    rules: [
    ...
    {
    test: /\.(png|svg|jpg|jpeg|gif)$/i,
    type: "assets/resource",
    }]
    }
    }
  • src 下载新建 assets/ 文件夹,放入一张图片:

  • index.js 中引入图片:

    import AbcImage from "./assets/abc.png"
    
    ...
    
    const image = document.createElement("img");
    image.src = AbcImage; document.body.prepend(image);
  • npx webpack

自动生成 HTML

上述的例子中,我们只是使用 webpack 来打包 jscss 文件,并手动的导入编写好的 html 中,使用下面的插件,就可以自动为我们生成 HTML 文件。

  • 安装插件:

    yarn add html-webpack-plugin --dev
  • 使用插件:

    const HtmlWebpackPlugin = require("html-webpack-plugin");
    ... plugins: [new HtmlWebpackPlugin({
    title: "博客列表",
    // 这里可以自定义网页的标题
    })],
  • npx webpack

    可以看到生成了和刚才相同的页面

使用 webpack 打包出来的网页没有显示 <h1>Hello World</h1> 的原因是 这个标签是我们自己写的

  • 定义打包好 html 文件的网页标题

    我们使用 html-webpack-plugins 打包生成的文件名默认是 Webpack App,其实网页标题是可以在插件内传递参数来更改的:

    plugins: [new HtmlWebpackPlugin({
    title: "博客列表",
    })],

Babel

有时我们的代码可能需要运行在更低版本的浏览器上,这些浏览器可能并不支持我们所写的更高级的代码,这时就需要用到 babel 转译工具来使我们的代码变成浏览器能够识别的代码。

  • 安装 babel-loader 相关依赖:

    yarn add --dev babel-loader @babel/core @babel/preset-env
  • webpack.config.js 中添加配置:

    rules: [
    ...
    {
    test: /\.js$/, // 识别js为结尾的文件
    exclude: /node_modules/, //不解释node_modules/下的文件
    use: {
    loader: "babel-loader",
    options: {
    presets: ["@babel/preset-env"]
    }
    }
    }]

    这里可以在 module.exports 下配置 devtool="inline-source-map" 方便查看打包后的源码

  • 使用 npx webpack 重新打包下,进入 dist/dist.js 查看相关代码:

    /* 打包前的 */
    blogs.forEach(blog => {
    const li = document.createElement("li");
    li.innerText = blog;
    ul.appendChild(li);
    })
    blogs.forEach(function (blog) {
    var li = document.createElement("li");
    li.innerText = blog;
    ul.appendChild(li);
    });

    可以看到 箭头函数已经被转换成了 .forEach 的形式,增强了对浏览器的兼容性。

使用 Terser 插件压缩打包后的代码

  • 安装插件:

    yarn add --dev terser-webpack-plugin
  • 配置:

    // webpack.config.js
    const TerserPlugin = require("terser-webpack-plugin"); module.exports = {
    ...
    optimization: {
    minimize: true,
    minimizer: [new TerserPlugin()],
    },
    }
  • 打包: npx webpack

    可以看到我们打包生成的 js 文件都被紧密地写在了一起,右键属性查看文件大小也要比之前的小一些。

使用 DevServer 插件自动打包

  • 安装:

    yarn add -dev webpack-dev-server
  • 配置:

    module.exports = {
    ...
    devServer: {
    static: "./dist",
    },
    }

    为了我们以后方便运行开发服务器,还需要在 package.json 里添加一个 script

    {
    ...
    "scripts": {
    "start": "webpack serve --open"
    },
    }
  • 启动服务器:

    yarn start
    // 或
    npm run start
  • 尝试一下 "热更新?"

    index.js 下添加如下代码:

    const header1 = document.createElement("h1");
    header1.innerText = "Hello";
    document.body.appendChild(header1);
  • 保存,查看网页

    这里不在使用 VsCodeLive Server 插件了,而是在浏览器地址栏输入命令行中输出的地址:

    成功!

    那么 webpack 是如何实现热更新的呢?其实是在我们每次保存时,插件自动生成新的 dist.js 并把之前的 dist.js 写入缓存,这或多或少会增加我们电脑的开销。但 webpack 贴心的为我们想到了这一点。

  • 每次打包生成新的 /dist.js

    配置 webpack.config.js

    output: {
    filename: "[name].[contenthash].js",
    // name 默认为 main
    path: path.resolve(__dirname, "dist"),
    },

    更改下 index.js 代码,运行 npx webpack

    可以看到生成了文件后缀名不同的文件,这样可以避免由于浏览器缓存机制而导致更新不及时的问题。

配置目录别名:

和之前写的 https://www.cnblogs.com/hhsk/p/16460701.html 大同小异

  • 配置:
    // webpack.config.js
    module.exports = {
    ...
    resolve: {
    alias: {
    assets: path.resolve(__dirname, "src/assets")
    }
    }
    }

30分钟掌握 Webpack的更多相关文章

  1. 30分钟学webpack实战

    阅读目录 一:什么是webpack? 他有什么优点? 二:如何安装和配置 三:理解webpack加载器 四:理解less-loader加载器的使用 五:理解babel-loader加载器的含义 六:了 ...

  2. 30分钟手把手教你学webpack实战

    30分钟手把手教你学webpack实战 阅读目录 一:什么是webpack? 他有什么优点? 二:如何安装和配置 三:理解webpack加载器 四:理解less-loader加载器的使用 五:理解ba ...

  3. 每天记录一点:NetCore获得配置文件 appsettings.json vue-router页面传值及接收值 详解webpack + vue + node 打造单页面(入门篇) 30分钟手把手教你学webpack实战 vue.js+webpack模块管理及组件开发

    每天记录一点:NetCore获得配置文件 appsettings.json   用NetCore做项目如果用EF  ORM在网上有很多的配置连接字符串,读取以及使用方法 由于很多朋友用的其他ORM如S ...

  4. 30分钟掌握ES6/ES2015核心内容(下)

    在 30分钟掌握ES6/ES2015核心内容(上)我们讲解了es6最常用的一些语法:let, const, class, extends, super, arrow functions, templa ...

  5. 【微信小程序项目实践总结】30分钟从陌生到熟悉 web app 、native app、hybrid app比较 30分钟ES6从陌生到熟悉 【原创】浅谈内存泄露 HTML5 五子棋 - JS/Canvas 游戏 meta 详解,html5 meta 标签日常设置 C#中回滚TransactionScope的使用方法和原理

    [微信小程序项目实践总结]30分钟从陌生到熟悉 前言 我们之前对小程序做了基本学习: 1. 微信小程序开发07-列表页面怎么做 2. 微信小程序开发06-一个业务页面的完成 3. 微信小程序开发05- ...

  6. 30分钟学会XAML

    1.狂妄的WPF 相对传统的Windows图形编程,需要做很多复杂的工作,引用许多不同的API.例如:WinForm(带控件表单).GDI+(2D图形).DirectX API(3D图形)以及流媒体和 ...

  7. Shell脚本编程30分钟入门

    Shell脚本编程30分钟入门 转载地址: Shell脚本编程30分钟入门 什么是Shell脚本 示例 看个例子吧: #!/bin/sh cd ~ mkdir shell_tut cd shell_t ...

  8. JS组件系列——又一款MVVM组件:Vue(一:30分钟搞定前端增删改查)

    前言:关于Vue框架,好几个月之前就听说过,了解一项新技术之后,总是处于观望状态,一直在犹豫要不要系统学习下.正好最近有点空,就去官网了解了下,看上去还不错的一个组件,就抽空研究了下.最近园子里vue ...

  9. 2016windows(10) wamp 最简单30分钟thrift入门使用讲解,实现php作为服务器和客户端的hello world

    2016最简单windows(10) wamp 30分钟thrift入门使用讲解,实现php作为服务器和客户端的hello world thrift是什么 最简单解释 thrift是用来帮助各个编程语 ...

随机推荐

  1. 从零开始手写Cartographer(1): 开端

    写在前面的话 我做SLAM已经三年了.读书时初学SLAM,一开始无从下手,直到读了高博士的博客,茅塞顿开,渐入佳境.后来又买了他的<视觉SLAM十四讲>,常伴手边,直至毕业.几个月前找工作 ...

  2. Redis_

    Redis学习 Redis学习(一) 1. NoSQL的引言 NoSQL(Not Only SQL ),意即不仅仅是SQL, 泛指非关系型的数据库.Nosql这个技术门类,早期就有人提出,发展至200 ...

  3. DQL条件查询模糊查询和约束概述

    模糊查询 -- 查询姓马的有哪些? like SELECT * FROM student where name LIKE '马%'; -- 查询姓名第二个字是化的人 SELECT * FROM stu ...

  4. vue中如何在自定义组件上使用v-model和.sync

    自定义事件 tips 推荐始终使用 kebab-case 的事件名.(v-on会将事件名自动转换为小写,避免匹配不到) changeData × change-data √ 自定义组件的v-model ...

  5. 15分钟搭建RocketMQ源码调试环境

    下载源码 下载源码,github页面选择(rocketmq-all-4.7.1)版本压缩包,https://github.com/apache/rocketmq/tags 导入IDEA 1. 使用ID ...

  6. YII学习总结2(命名空间和操作响应)

    YII基础准备1.命名空间<?php /****假设有三个同名的类,输出的值为A,B,C****/ use a\b\c\apple; use d\e\f\apple as bApple; use ...

  7. Apache DolphinScheduler 架构演进 & Roadmap

    <DataFunSummit:大数据存储架构峰会> 2021年4月17日Apache DolphinScheduler PMC chair 代立冬参与 DataFunSummit 分享&l ...

  8. Luogu P1903 [国家集训队]数颜色 / 维护队列 (带修莫队)

    #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> ...

  9. ESP32与MicroPython入门-01 搭建开发环境

    ESP32简介 ESP32 是上海乐鑫公司开发的一款比较新的32位微控制器,它集成了WiFi及蓝牙等功能,有着性能稳定.功耗低.价格低廉等特点,非常适用于物联网开发,但也可以作为普通的MCU使用. E ...

  10. Unity3D学习笔记12——渲染纹理

    目录 1. 概述 2. 详论 3. 问题 1. 概述 在文章<Unity3D学习笔记11--后处理>中论述了后处理是帧缓存(Framebuffer)技术实现之一:而另外一个帧缓存技术实现就 ...