从0开始学习webpack打包,效率与性能“快的飞起”

 

 

​ 前言

本篇文章我会带你从0开始学习webpack,这是webpack系列文章的第一篇,后续会持续更新。

 

 为什么会出现模块化开发

模块化,可以说是当下最重要的前端开发范式之一。随着前端应用的日益复杂化,我们的项目已经逐渐膨胀到了不得不花大量时间去管理的程度。而模块化就是一种最主流的项目组织方式,它通过把复杂的代码按照功能划分为不同的模块单独维护,从而提高开发效率、降低维护成本。

模块化打包需要具有以下的功能

  •  能够将零散的模块打包到一起

  •  能够编译代码中的新特性

  •  能够支持不同类型的前端资源模块

目前主流的打包工具有webpack、Parcel和Rollup。他们都可以满足以上的需求,这里以webpack为例。

  • webpack作为一个模块打包工具,可以将许多零散的JS文件打包到一个JS文件中

  • 它可以通过loader机制对有环境兼容问题的代码进行编译转换后再打包

  • 它支持载入任意类型的文件,例如可以在JS文件中加载CSS

  • 它具有代码拆分的能力,可以将所有的模块按照我们的需要进行分块打包,这样可以解决避免单个文件过大,加载较慢的问题

我们可以将初次加载所需要的内容打包到一个文件中,其他的模块可以分开打包,等到需要的时候再进行异步加载模块,实现增量加载,也叫渐进式加载。

熟悉VUE的朋友大家都知道,我们习惯了使用VUE-CLI搭建VUE项目,项目中已经帮助我们配置好了webpack的相关配置,基本上我们很少需要去手动的去更改它的配置,因为我们觉得npm run build后可以运行就完了。但是要想成为一个高级的前端工程师,必须要知道如何去使打包后的体积更小,加载更快,提高运行效率。

 

从0开始学习webpack打包,效率与性能“快的飞起”_第1张图片

首先根据以下的结构新建目录

├── src
   │   ├── holle.js
   │   └── index.js
   └── index.html

src/hello.js

export default () =>{
    const element = document.createElement('h2')
    element.textContent = 'Hello webpack'
    element.addEventListener('click', () =>{
        alert('Hello webpack')
    })
    return element
}

src/index.js

imimport hello from './hello'
const sayHello = hello()
document.body.append(sayHello)

index.html




    
    
    webpack


    

在上面我们可以看到type=‘module’,这是ES Modules中提出的标准,用来区分加载的是一个脚本还是一个模块,对于支持ES modules标准的浏览器是可以正常运行index.html的,我专门去看了一下现在浏览器对ES Modules支持的情况。ES modules是未来标准发展的一种趋势。

从0开始学习webpack打包,效率与性能“快的飞起”_第2张图片

在src/hello.js中导出了一个创建元素的函数,在src/index.js中引入这个模块,并执行创建元素函数,然后添加到body中。我们在开发时进行模块化的开发,可以使结构更加的清晰,功能划分明确,但是在线上环境中,引入众多的模块会显得非常的繁琐,webpack的工作就可以帮助我们把众多的模块合并起来。

首先在工作目录执行

npm init --yes

初始化一个package.json文件,用来管理npm的所有依赖。

安装webpack与webpack-cli

npm install webpack webpack-cli --save

webpack是webpack的核心模块

webpack-cli是Webpack的CLI程序,用来在命令行中调用webpack

$ npx webpack --versionv4.42.1

npx是npm5.2后新增的一个命令,他可以方便的执行远程模块或项目node_modules中的CLI程序,我们刚才安装的webpack-cli就在node_modules中,接下来我们就可以运行webpack命令来进行打包。

$ npx webpack

从0开始学习webpack打包,效率与性能“快的飞起”_第3张图片

打包完成后在当前目录或多一个dist文件夹,里面有一个main.js,这个就是打包后的js文件。在控制台也可以看到打包的一些信息,包括打包了那些文件,他们的大小等信息。

现在把index.html中script标签路径替换为打包后的js文件,并去掉type=‘module’,如下所示:




    
    
    webpack


    

在浏览器中打开页面,可以看到我们预期的结果

刚才我们就经历了一个webpack的打包过程,看起来也就那样。接下来我们对打包过程加入一些自己的配置。

在当前目录下新建一个webpack.config.js文件,这就是webpack的配置文件,如果这个文件存在,webpack会根据文件中的配置进行打包。

//webpack.config.js
const path = require('path')
module.exports = {
    mode: 'development',
    entry: './src/index.js',
    output: {
        filename: 'develpoment.js',
        path: path.join(__dirname, 'output')
    }
}

这里只写了3个属性,更多的属性可以在webpack的官网中进行查看。

mode(模式):有三个可选值(none/development/production),我们可以根据不用的环境来选择相应的打包方式。

  • none:运行最原始的打包,不做任何处理

  • development:自动优化打包速度,添加一些调试过程中的辅助工具

  • production:启动内置优化插件,优化打包结果,但是打包速度较慢。主要用于生产环境

也可以在cli中以参数的形式选择

webpack --mode=production

entry(入口):指示 webpack 应该使用哪个模块,来作为构建其内部依赖图的开始。进入入口起点后,webpack 会找出有哪些模块和库是入口起点(直接和间接)依赖的。

output(出口):告诉 webpack 在哪里输出它所创建的 bundles,以及如何命名这些文件,默认值为 ./dist。基本上,整个应用程序结构,都会被编译到你指定的输出路径的文件夹中。通过 output.filename 和 output.path 属性,来告诉 webpack bundle 的名称,以及我们想要 bundle 生成(emit)到哪里。

在上面我们用到了path模块,它是属于node.js的模块,因为webpack.config.js是运行在node.js环境中的代码,所以这里可以使用node.js的内置模块。

如果觉得我的文章对你有有所帮助的话,可以关注我的公众号【前端筱园】,也欢迎访问我的个人网站:www.dzyong.top。

 打包结果的运行原理

我们把模式设置为none,使用最原始的打包模式,来分析打包后的文件。

把所有的内容先折叠,可以看到打包后的js文件是一个立即执行函数,该函数接收一个数组作为参数。

从0开始学习webpack打包,效率与性能“快的飞起”_第4张图片

打开数组参数,可以看到该数组就是我们所需要打包的两个模块。

从0开始学习webpack打包,效率与性能“快的飞起”_第5张图片

在函数的内部可以分为四大部分

  • installedModules用于缓存加载过的模块

  • __webpack_require__用于加载指定模块的函数

  • 对__webpack_require__函数挂载一些其他的数据和工具函数

  • 最后return中开始加载源代码的入口模块

从0开始学习webpack打包,效率与性能“快的飞起”_第6张图片

打开加载模块函数内部,函数接收的moduleId就是数组的下标,从上面的图的最后可以看到,第一次传入的值为0,也就是从第一个模块开始。

从0开始学习webpack打包,效率与性能“快的飞起”_第7张图片

  • 第一步先在缓存对象中查看是否已经含有该模块,如果存在则直接返回。
  • 如果不存在,则加入到缓存对象中,设置加载标记为false,也就是其中的属性 l 。
  • 然后执行模块功能,将模块标记为已加载,最后返回模块。

经过分析后可以发现其实打包的原理并不难,只是在平时中只知道怎么用就行了,并没有关心过它的过程。就好比VUE一样,现在随便前端人员都会使用VUE,但是当我们知道VUE的底层有原理后,可以帮助我们更好的更灵活的去运用它,遇到问题也可以更快速的定位到问题所在。这就是为什么我们一定要去了解他们的工作原来,也可以帮助我们拓展更广泛的思维。

 

你可能感兴趣的:(webpack,JavaScript)