本文基于:峰华前端工程师--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. 4-11 Spring Security及SSO

    1. 关于用户身份认证与授权 Spring Security是用于解决认证与授权的框架. 在根项目下创建新的csmall-passport子模块,最基础的依赖项包括spring-boot-starte ...

  2. 多校B层冲刺NOIP20211110 字符配对游戏

    原题 问题描述 操场边,运动会没有项目的同学也没闲着,经过几天的研究,他们发明了一个很有意思的字符串配对游戏,两位同学准备两张白纸,第一个同学在纸上写一个整数N和一个由小写字母组成的字符串S,将S重复 ...

  3. 在less里面使用js函数

    .colorPaletteMixin() { @functions: ~`(function() { this.colorPalette = function() { return '123px'; ...

  4. 枚举子集为什么是 O(3^n) 的

    这是更新日志 \(2021/2/9\) 代数推导 \(2021/2/10\) 组合意义,构建 TOC 目录 枚举子集 复杂度证明 代数推导 组合意义 Summary 枚举子集 枚举子集为什么是 \(O ...

  5. AWS EKS 创建k8s生产环境实例

    #AWS EKS 创建k8s生产环境实例 在AWS部署海外节点, 图简单使用web控制台创建VPC和k8s集群出错(k8s), 使用cli命令行工具创建成功 本实例为复盘, 记录aws命令行工具创建e ...

  6. [LNOI2022]盒

    \(LNOI2022\)盒 由于是加的形式,那么可以套路的拆贡献,枚举每条边的贡献就好了 \(40pts\) //比较显然的事情 //首先确定了一个B数组之后 //最小的移动应该是 //设左右两侧比原 ...

  7. 喜讯:“行走的文档” 当选 Apache DolphinScheduler Committer啦

    点击上方蓝字关注 Apache DolphinScheduler Apache DolphinScheduler(incubating),简称"DS", 中文名 "海豚调 ...

  8. Apache DolphinScheduler 是如何诞生的

    作者 | 代立冬,李岗 排版 | 开源之道小助理 Apache DolphinScheduler,简称"DS", 中文名 "小海豚调度"(海豚聪明.人性化,又左 ...

  9. 在.NET 6.0中使用不同的托管模型

    大家好,我是张飞洪,感谢您的阅读,我会不定期和你分享学习心得,希望我的文章能成为你成长路上的垫脚石,让我们一起精进. 本章是<定制ASP NET 6.0框架系列文章>的第六篇.在本章中,我 ...

  10. thinkphp 5 及一下或php项目里实现模糊查询

    想在thinkPHP或者PHP项目实现模糊查询怎么实现呢? 今天在网上搜了一下用 mysql里的 like 就可以实现 怎么用呢? 看代码: 错误用法: where('title','like',$s ...