1. 为什么需要模块化打包工具

在上一篇文章中提到的ES Module可以帮助开发者更好地组织代码,完成js文件的模块化,基本解决了模块化的问题,但是实际开发中仅仅完成js文件的模块化是不够的,尤其是面对一个较为庞大的工程项目的时候,主要仍有以下几个问题需要解决:

  1. ES Module是ES6新语法,一些老的浏览器不支持
  2. 每个模块对应一个script标签,模块划分过于细致的时候,网络请求次数多,页面会卡顿。(在开发过程中,划分多个模块是有益于代码组织的,但是生产运行的时候,不需要这么多模块,过多的模块反而会影响页面加载效率)
  3. 不光JS文件需要模块化,其他不同种类的资源(包括css文件等)都要完成模块化

前2个问题都可以通过一些插件来解决,但是第3个问题支持多种文件就比较复杂,不太好处理,这时就需要使用到模块化打包工具。

2.模块化打包工具的功能

  1. 模块打包:完成多个模块的打包,将多个模块的js文件打包到一个js里面。
  2. loader转换: 以webpack为例,可以使用loader完成格式的转换,改善兼容性问题
  3. 代码拆分:可以拆分不同模块的代码,没用到的代码,实现异步加载,渐进式加载
  4. 可以以模块化的方式载入各种类型的文件,比如import一个css文件

打包工具解决的是前端整体的模块化,不只是局限于js的模块化

3. Webpack尝试

3.1安装与基本使用

安装webpack

npm install webpack webpack-cli

最简单使用,文件结构如下,项目里只有一个index.html和一个src文件夹,src文件夹里有2个js文件

project
├── index.html
└── src
├── index.js
└── heading.js
  • index.html里内容如下,只有一句,就是以模块化的方式引入了index.js,index.js里则是导入了heading.js的内容
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Webpack - 快速上手</title>
</head>
<body>
<script type="module" src="./src/index.js"></script>
</body>
</html>

然后在项目根目录(project文件夹)下打开cmd窗口,输入npx webpack,就已经完成了打包,此时项目的根目录下多出一个dist文件夹,里面有一个main.js文件,将main.js引入后到html后网页功能一切正常使用

这个可以看出,webpack已经完成了打包,也就是把原本的2个模块,打包成了1个js文件来输出

3.2配置文件

在项目的根目录下添加webpack.config.js文件,这就是webpack的配置文件,这是一个运行在node环境下的js文件,所以需要使用CommonJS规范去编写代码。

最基本的配置如下,在配置文件里规定打包的入口,输出的地址和文件名

const path = require('path')

module.exports = {
entry: './src/main.js', //指定打包入口文件的路径
output: {
filename: 'bundle.js', //输出的文件名
path: path.join(__dirname, 'output') //打包完后输出的路径
}
}

3.3工作模式

在之前的打包过程中,虽然可以正常打包,但是会有一个警告,显示没有设置mode配置项,并且自动将mode设置为production。想要配置工作模式就需要去webpack.config.js文件去配置一个mode属性,这个属性有三种取值,分别是 production、development 和 none。

以开发模式为例

const path = require('path')

module.exports = {
mode:'development',
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.join(__dirname, 'dist')
}
}

不同的工作模式会有不同的打包方式

  1. 生产模式下,Webpack 会自动优化打包结果;
  2. 开发模式下,Webpack 会自动优化打包速度,添加一些调试过程中的辅助;
  3. None 模式下,Webpack 就是运行最原始的打包,不做任何额外处理;

同一个简单项目,在生产和开发模式下打包出来的js文件对比

生产模式只有短短两行代码,并且做了对应的压缩和优化处理

开发模式的代码直截图了一小部分,整个代码较长,加入了许多调试相关的内容,但是也更方便阅读

3.4打包后的内容

想了解一下打包的过程,可以直接把前面的工作模式改成none,让他打包的时候不做额外处理,然后运行打包命令。

整体结构:最终的输出js文件在折叠后如下图所示,就是一个立即执行函数,函数接收一个参数modules,modules是一个数组

函数参数 这个modules数组里的每个元素都是一个参数列表相同的函数,这每一个函数都是对应源代码里的一个模块,也就是说每个模块在打包后都会被包裹在这样一个函数中,而包裹函数这样的作法就直接实现了不同模块之间的私有作用域,这样不会产生变量冲突和污染

立即执行函数的主体 对于webpack的工作模块,他首先检查了是否存在缓存,然后定义了一个__webpack_require__的方法,最后调用了这个方法,moudleId这个参数值是模块在之前的数组里的索引,处理第一个模块就传0,第二个传1......

__webpack_require__方法内部,先是创建了module对象,然后调用了一开始立即执行函数的参数,并且传入了模块对象,exports对象,和__webpack_require__函数

立即执行函数的参数的函数内部  调用了这个方法之后,就可以在模块的内部使用module.export去导出成员使用require去载入模块了

先是调用了__webpack_require__.r方法给exports对象加了一个es module的标记,然后执行__webpack_require__(1),也就是对这个模块导入的另外一个模块,进行相同的操作,让那个模块也可以在模块的内部使用module.export去导出成员使用require去载入模块了

3.4加载css文件

webpack是整个前端项目的模块化打包工具,也有打包css的能力,但是默认的loader只支持js的加载,所以这就需要使用到css-loader和style-loader

安装css-loader

npm i css-loader style-loader

安装完后先在src文件夹下新建一个css文件,然后写点最简单的改变背景色代码,要把css加载到html里需要在webpack.config.js中做一些配置

  1. 修改打包的入口文件为新建的css文件(只是尝试一下,一般推荐把js文件当作入口文件)
  2. 加入module属性,module属性是一个对象,在module里加入loader的匹配规则
const path = require('path')
module.exports = {
    mode: 'none',
    entry: './src/index.css',
    output: {
        filename: 'bundle.js',
        path: path.join(__dirname, 'dist')
    },
    module: {
        rules: [
            {
                use: [
                    'style-loader',
                    'css-loader'
                ],
                test: /.css$/,   //以.css结尾的文件用这些loader去处理
            }
        ]
    }
}

运行打包命令后可以看到bundle.js里已经有对应的代码了,css-loader将css文件变成了字符串并且push进了一个数组,然后再通过style-loader创建了对应的style标签插入了html里面

整个背景都已经变成红色,说明css已经被成功加载

3.4webpack加载资源文件

打包入口

刚才加载css文件的时候修改了打包的入口文件把js文件改成了css文件,但是一般都会把入口文件设置成js文件,然后通过import的方式去引入css或者图片文件,虽然看起来的确繁琐,但是这也体现了所有资源的引入都依赖代码这个思想

  • index.js
import createHeading from './heading.js'
import './index.css' const heading = createHeading() console.log(111)

在webpack.config.js的配置里入口文件仍然设置为index.js

const path = require('path')

module.exports = {
mode: 'none',
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.join(__dirname, 'dist')
},
module: {
rules: [
{
use: [
'style-loader',
'css-loader'
],
test: /.css$/
}
]
}
}

设置publicPath

除了css文件,还有图片文件也需要引入js,这里有一个创建图片并且添加进html的功能

import createHeading from './heading.js'
import './main.css'
import icon from './icon.png' const heading = createHeading() document.body.append(heading) const img = new Image()
img.src = icon document.body.append(img)

此时需要用到file-loader,需要先安装file-loader,然后配置对应的loader规则(在配置文件的rules数组里加一项针对file-loader的配置项)

npm install file-loader

除了file-loader,还需要在output配置项里加入一个publicPath属性,这个属性表示打包后的内容在项目的哪个位置,默认值是空字符串,也就是说webpack会默认认为它打包好的内容会放在网站的根目录下,然而实际上根据我们的文件结构,并没有直接放在网站根目录下。

网站的根目录是index.html所在的外层,而打包的内容全在dist目录下(dist目录下也没有html文件)

直接使用默认值会导致图片路径加载的错误,它会在index.html所在的文件夹里寻找图片文件,然而图片的真实路径是在dist文件夹下,那就一定加载不出来了

我们打包后的结果在dist文件夹下,所以publicPath就写dist/。

const path = require('path')

module.exports = {
mode: 'none',
entry: './src/main.js',
output: {
filename: 'bundle.js',
path: path.join(__dirname, 'dist'),
publicPath: 'dist/'
},
module: {
rules: [
{
test: /.css$/,
use: [
'style-loader',
'css-loader'
]
},
{
test: /.png$/,
use: 'file-loader'
}
]
}
}

转换成dataurl

处理图片等文件的时候,可以使用dataurl来减少发送请求的次数,提升网站的性能。dataurl里面就直接写了一个文件的内容,像图片就通过base64编码直接写在里面了,而html则是写了html代码

安装url-loader

npm install url-loader

配值对应的规则,把use从原来的字符串换成一个对象,加入loader和limit属性,表示小于10KB的png图片,直接通过url-loader把它转换成base64编码格式的图片,而大于10KB的图片,url-loader会自动调用file-loader把它复制到dist文件夹下,并且引入,所以使用url-loader的时候,必须要有file-loader

const path = require('path')

module.exports = {
mode: 'none',
entry: './src/main.js',
output: {
filename: 'bundle.js',
path: path.join(__dirname, 'dist'),
publicPath: 'dist/'
},
module: {
rules: [
{
test: /.css$/,
use: [
'style-loader',
'css-loader'
]
},
{
test: /.png$/,
use: {
loader: 'url-loader',
options: {
limit: 10 * 1024 // 10 KB
}
}
}
]
}
}

模块化打包工具-初识Webpack的更多相关文章

  1. 透过实现小型打包工具理解webpack

    面试经常有问到 webpack,偶遇一篇比较有实用价值的且有利于理解的文章,现总结如下: 本篇文章中要实现的这个迷你打包工具,它主要能实现如下两个功能: ①.将 ES6 转换成 ES5: ②.支持在 ...

  2. Webpack实战(一):Webpack打包工具安装及参数配置

    为什么要模块化 javascript跟其他开发语言有很多的区别,其中一个就是没有模块化概念,如果一个项目中有多个js文件,我们只能通过script标签引入的方式,把一个个js文件插入到页面,这种做法会 ...

  3. 浅谈Webpack模块打包工具一

    为什么要使用模块打包工具 1.模块化开发ES Modules存在兼容性问题 打包之后成产阶段编译为ES5 解决兼容性问题 2.模块文件过多 网络请求频繁  开发阶段把散的模块打包成一个模块 解决网络请 ...

  4. 总结Vue第三天:模块化和webpack模块化打包:

    总结Vue第三天:模块化和webpack模块化打包: 一.❀ 模块化 [导入import-----导出export] 1.为什么需要模块化? JavaScript 发展初期,代码简单地堆积在一起,只要 ...

  5. Webpack:前端资源模块化管理和打包工具

    一.介绍: Webpack 是当下最热门的前端资源模块化管理和打包工具.它可以将许多松散的模块按照依赖和规则打包成符合生 产环境部署的前端资源.还可以将按需加载的模块进行代码分隔,等到实际需要的时候再 ...

  6. 模块化管理工具兼打包工具 webpack

    webpack 是一个[模块化管理工具]兼[打包工具] 是一个工具(和seajs,requirejs管理前端模块的方式是不一样) 在webpack一个文件就是一个模块! seajs,requirejs ...

  7. webpack模块化管理和打包工具

    Webpack简介 webpack是当下最热门的前端资源模块化管理和打包工具.它可以将许多松散的模块按照依赖和规则打包成符合生产环境部署的前端资源.还可以将按需加载的模块进行代码分隔,等到实际 需要的 ...

  8. Angular (SPA) WebPack模块化打包、按需加载解决方案完整实现

    文艺小说-?2F,言情小说-?3F,武侠小说-?9F long long ago time-1-1:A 使用工具,long long A ago time-1-2:A 使用分类工具,long long ...

  9. Webpack与其他打包工具的区别

    webpack是一个模块化加载器兼打包工具,它同时支持AMD.CMD等加载规范.与其他模块化加载器相比,它有这些优势: 1.代码分割 webpack支持两种依赖加载:同步和异步.同步的依赖会在编译时直 ...

  10. Webpack打包工具学习使用

    Webpack 是当下最热门的前端资源模块化管理和打包工具.它可以将许多松散的模块按照依赖和规则打包成符合生产环境部署的前端资源.还可以将按需加载的模块进行代码分隔,等到实际需要的时候再异步加载.通过 ...

随机推荐

  1. @Target元注解的使用

    @Target注解标记另外的注解用于限制此注解可以应用哪种Java元素类型.先看Java SE 8中@Target是如何声明的: package java.lang.annotation; publi ...

  2. 第四章 VIVIM编辑器

    1. 是什么 ‍ VI 是 Unix 操作系统和类 Unix 操作系统中最通用的文本编辑器. ‍ VIM 编辑器是从 VI 发展出来的一个性能更强大的文本编辑器. ‍ 2. 一般模式 ‍ 以 vi/v ...

  3. 人工智能政策@🤗: 回应美国国家电信和信息管理局 (NTIA) 关于人工智能问责制的评论请求

    6 月 12 日,Hugging Face 向美国国家电信和信息管理局 NTIA 提交了一份关于 AI 责任政策的信息请求回应.在我们的回应中,我们强调了文档和透明度规范在推动 AI 责任过程中的作用 ...

  4. PHP生成随机中文姓名

    <?phpfunction &xingming(){ for ($i = 0; $i < 1; $i++) { $xing = "赵,钱,孙,李,周,吴,郑,王,冯,陈, ...

  5. 什么是 CSR、SSR、SSG、ISR - 渲染模式详解

    本文以 React.Vue 为例,介绍下主流的渲染模式以及在主流框架中如何实现上述的渲染模式. 前置知识介绍 看渲染模式之前我们先看下几个主流框架所提供的相关能力,了解的可跳到下个章节. 挂载组件到 ...

  6. 一键搞定发布自己Jar到Maven中央仓库

    做java 开发那当然离不开jar包管理, 不知何时一直想想封装一个自己的jar包 然后发布到maven中央仓库给别人使用. hhh 我感觉自己写一个jar包工具然后,被很多人使用是一件很牛,很快乐事 ...

  7. P2709 小B的询问题解

    本题需要用到莫队算法 关于莫队算法 莫队算法是一种离线算法,适用于序列中统计区间特定的目标的问题. 时间复杂度通常是 \(O(n \sqrt n)\) 或更高. P2709 小B的询问 点击查看原题 ...

  8. AcWing 第87场周赛题解

    T1 移动棋子 算出数值为 \(1\) 的点离 \((3, 3)\) 的距离即可. #include <iostream> #include <cstring> #includ ...

  9. 五分钟教你使用GitHub寻找优质项目

    前言 经常会有同学会问如何使用GitHub找到自己想要的项目,今天咱们就出一期快速入门教程五分钟教你使用GitHub寻找优质项目.GitHub作为世界上最大的项目开源平台之一,上面有着无数优质的开源项 ...

  10. Kubernets常用命令

    查看所有namespace的pods运行情况 kubectl get pods --all-namespaces kubectl get service -ALL kubectl get deploy ...