写点什么

构建系列之 webpack 窥探下

作者:江湖修行
  • 2023-05-22
    北京
  • 本文字数:2890 字

    阅读完需:约 9 分钟

构建系列之webpack窥探下

Webpack 实线

安装

全局安装 webpack


npm install -g webpack
复制代码


进入项目目录,生成 package.json 文件


npm init
//对应的package.json文件{ "name": "test", "version": "1.0.0", "description": "package.json test", "main": "webpack.config.js", "dependencies": { "webpack": "^4.46.0" }, "devDependencies": {}, "scripts": { "build": "webpack" //加上这一句,当我们执行npm run build时它会去我们局部的webpack中去寻找命令,如果找不到再去全局寻找 }, "author": "jianghuxiuxing", "license": "ISC"}
复制代码


安装 webpack 依赖


npm install webpack --save-dev
复制代码

编译打包

新建 index.html


// 在页面中引入test.js<script src="test.js"></script>
复制代码


新建入口文件 main.js


alert('hello world')
复制代码


编译 main.js 并打包到 test.js


webpack main.js test.js
// 此时会自动生成test.js文件// 运行index.html将弹出:hello world
复制代码


新建模块 module.js,并修改 main.js


// module.jsmodule.exports = 'It is module.js!'
// main.jsalert('hello world');alert(require('./module.js'))
// 再次编译打包,后刷新页面// 其它模块可同样类似引入
复制代码

css 文件处理

loader 是 webpack 中一个非常核心的概念,前面提到 loader 是主要用来做文件转化的。虽然 js 代码我们可以用 webpack 处理并且 webpack 会自动处理 js 之间相关的依赖。但是在开发中我们不仅仅有基本的 js 代码处理,我们也需要加载 css、图片,也包括一些高级的将 ES6 转成 ES5 代码,将 TypeScript 转成 ES5 代码,将 scss、less 转成 css,将.jsx、.vue 文件转成 js 文件等等。对于 webpack 本身的能力来说,对于这些转化是不支持的,所以就需要给 webpack 扩展对应的 loader。


loader 使用过程:


步骤一:通过 npm 安装需要使用的 loader


步骤二:在 webpack.config.js 中的 modules 关键字下进行配置


大部分 loader 我们都可以在 webpack 的官网中找到,并且学习对应的用法。


引入 css loader


npm install css-loader style-loader
复制代码


去掉 loader 前缀


// 通过新建文件webpack.config.jsvar webpack = require('webpack')module.exports = {  entry: './main.js',  output: {    path: __dir,    filename: 'test.js'  },  module: {    loaders: [      {test: /.css$/, loader: 'style-loader!css-loader'}    ]  }}
复制代码


在 main.js 中引入 style.css


require("./style.css")
复制代码


引入 less loader


需要安装对应的 loader。注意:我们这里还安装了 less,因为 webpack 会使用 less 对 less 文件进行编译。其次,修改对应的配置文件,添加一个 rules 选项,用于处理.less 文件


npm install --save-dev less-loader less
复制代码


{    test: /.css$/,     use: [{loader:'style-loader'},{loader:'css-loader'},    {loader:'less-loader'}    ]}
复制代码

ES6 语法处理

在没有引入 babel 等能力的时候,webpack 打包后的 js 文件的 ES6 语法并没有转成 ES5,那么就意味着可能一些对 ES6 还不支持的浏览器没有办法很好的运行我们的代码。在 webpack 中,通过 babel-loader 的方式来接入 babel 的能力,babel 配置文件与单独使用 babel 时相同。


npm install --save-dev babel-loader@7 babel-core babel-preset-es2015
复制代码


在 webpack 中使用 babel 时建议开启 babel 的缓存能力,即 cacheDiretory,统计显示,在大型项目中,构建速度可以提升近 1 倍,webpack 的配置文件示例如下:


 module: {    rules: [      {        test: /.[j,t]sx?$/,        exclude: /node_modules/,        use: {          loader: 'babel-loader?cacheDirectory'        }      }    ]  }
复制代码

监听

webpack main.js test.js --watch
复制代码

webpack 扩展

webpack 基于其强大的扩展能力,可以让开发者更轻松的定制化实现需求。如果你在社区找不到你的应用场景的解决方案,那就需要自己动手了写 loader 或者 plugin 了。


webpack loader,以 comment-require-loader 为例:


module.exports = function (content) {    return replace(content);};
复制代码


loader 的入口需要导出一个函数,这个函数要干的事情就是转换一个文件的内容。函数接收的参数 content 是一个文件在转换前的字符串形式内容,需要返回一个新的字符串形式内容作为转换后的结果,所有通过模块化导入的文件都会经过 loader。从这里可以看出 loader 只能处理一个个单独的文件而不能处理代码块。


webpack plugin 的两个核心概念:


  • compiler:从 webpack 启动到退出只存在一个 Compiler,compiler 存放着 webpack 的配置。

  • compilation:由于 webpack 的监听文件变化自动编译机制,compilation 代表一次编译。


Compiler 和 Compilation 都会分发一系列事件。webpack 生命周期里有非常多的事件,开发者可以根据对应的事件节点定制自己的功能​。


以 end-webpack-plugin 为例:


class EndWebpackPlugin {
constructor(doneCallback, failCallback) { this.doneCallback = doneCallback; this.failCallback = failCallback; }
apply(compiler) { // 监听webpack生命周期里的事件,做相应的处理 compiler.plugin('done', (stats) => { this.doneCallback(stats); }); compiler.plugin('failed', (err) => { this.failCallback(err); }); }}
module.exports = EndWebpackPlugin;
复制代码

常见的 loader

  • babel-loader:把 es6 转成 es5;

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

  • style-loader:把 css 代码注入到 js 中,通过 dom 操作去加载 css;

  • eslint-loader:通过 Eslint 检查 js 代码;

  • image-loader:加载并且压缩图片;

  • file-loader:文件输出到一个文件夹中,在代码中通过相对 url 去引用输出的文件;

  • url-loader:和 file-loader 类似,文件很小的时候可以 base64 方式把文件内容注入到代码中。

  • source-map-loader:加载额外的 source map 文件,方便调试。

常见的 plugin

  • uglifyjs-webpack-plugin:通过 UglifyJS 去压缩 js 代码;

  • commons-chunk-plugin:提取公共代码;

  • define-plugin:定义环境变量。

loader 和 plugin 的不同

作用不同:


  • loader 让 webpack 有加载和解析非 js 的能力;

  • plugin 可以扩展 webpack 功能,在 webpack 运行周期中会分发很多事件,plugin 可以监听这些事件,并调用 webpack 提供的相应的 api 丰富现有的能力。


用法不同:


  • loader 在 module.rule 中配置。类型为数组,每一项都是 Object;

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

总结

在前端卷的无法自拔的情形下,各大脚手架或构建工具层出不穷,最近的 Turbopack 更是宣扬自己比 webpack 快 700 倍,虽说真实场景和数据可信度暂且不论,就形与势来说我们不能仅专注一个构建工具的使用,更不能只停留在表层不深入研究其原理。但不管是老旧项目难以更新换代脱离 webpack 的束缚,还是 webpack 本身的不断进化,我们总之是可以看到 webpack 的架构扩展、插件化等优秀理念的,所以我们要时刻保持着敬畏之心,毕竟技术的推陈出新也是踩在巨人的肩膀上完成的,技术没有银弹,我们需要根据自己的场景选择适用于当下及未来一段时间内的可控变化权衡后​所选用的技术。微信首发构建系列之webpack窥探下,欢迎关注微信公众号。

发布于: 刚刚阅读数: 4
用户头像

江湖修行

关注

还未添加个人签名 2021-12-05 加入

还未添加个人简介

评论

发布
暂无评论
构建系列之webpack窥探下_前端_江湖修行_InfoQ写作社区