前端利器躬行记(3)——webpack基础

简介:   webpack是一个静态模块打包器,此处的模块可以是任意文件,包括Sass、TypeScript、模板和图像等。webpack可根据输入文件的依赖关系,打包输出浏览器可识别的JavaScript、CSS和HTML等文件,并且能对图像做优化处理,如图1所示。

  webpack是一个静态模块打包器,此处的模块可以是任意文件,包括Sass、TypeScript、模板和图像等。webpack可根据输入文件的依赖关系,打包输出浏览器可识别的JavaScript、CSS和HTML等文件,并且能对图像做优化处理,如图1所示。


5.png

图1  webpack打包

  目前,webpack的最新版本是4.33,其配置文件(webpack.config.js)的基本结构如下所示,包含了它的4个核心概念:入口(entry)、输出(output)、加载器

(loader)和插件(plugin)。
module.exports = {
  entry: {},               //入口
  output: {},              //输出
  module: { rules: [] },    //加载器
  plugins: []              //插件
};


一、安装


  如果要安装最新版本的webpack,那么可以运行下面这条命令。

npm install --save-dev webpack

  当使用的是webpack 4+版本时,还需要再安装它的命令行工具,安装命令如下所示。

npm install --save-dev webpack-cli

  接下来就可以运行webpack的打包命令了,如下所示,其中“--config”参数后面会跟着配置文件的路径。

npx webpack --config webpack.config.js

  通过package.json的scripts字段可声明自定义的脚本任务(如下代码所示),从而就能快捷的执行打包命令,例如“npm run build”。

{
  scripts: {
    build: "npx webpack --config webpack.config.js"
  }
}


二、入口


  在webpack.config.js中,entry字段是一个入口,记录着需要处理的模块。从这个入口开始,webpack会递归地构建出模块之间的依赖关系。

1)单个入口

  当entry字段是一个字符串类型时,其值就是模块的相对或绝对路径,如下所示。

module.exports = {
  entry: "./index.js"
};

  这其实是一种简写,等价于下面的对象形式。对象的键就是chunk的名称,chunk是webpack的特定术语,通常一个chunk对应或多个chunk组成一个bundle(即打包生成的文件)。

module.exports = {
  entry: "./index.js"
};

  entry字段的值既可以是对象和字符串,也可以是由模块路径组成的数组,如下代码所示,其中index.js和list.js两个文件会被合并成一个chunk。

module.exports = {
  entry: ["./index.js", "./list.js"]
};

2)多个入口

  只要在entry的对象中添加多个属性就能设置多个入口,如下所示。

module.exports = {
  entry: {
    index: "./index.js",
    list: __dirname + "/list.js"
  }
};

  两个chunk会被分别命名为index和list,其中__dirname是Node.js内置的全局变量,保存着当前文件所处目录的绝对路径。


三、输出


  在webpack.config.js中,output字段是一个对象,用于配置输出的信息。它的filename属性可声明输出的文件名,而另一个path属性可配置输出目录的绝对路径。与入口不同,在配置文件中只能存在一个输出。

1)filename

  如果在入口中声明了多个chunk,那么在配置输出时得用占位符来表示对应的bundle名称,如下所示。


module.exports = {
  entry: {
    index: "./index.js",
    list:  "./list.js"
  },
  output: {
    filename: "[name].bundle.js"
  }
};


  [name]表示chunk的名称,例如index和list,还有另外三个常用的占位符,如表3所示。

表3  filename中的占位符

占位符 描述
[id] chunk的唯一标识符
[hash] chunk的唯一标识符的hash值
[chunkhash] chunk内容的hash值

  [hash]常与[name]配合使用(如下所示),在运行打包命令后,默认会在配置文件所处的位置创建dist目录,并且把生成的bundle文件放置其中。

module.exports = {
  output: {
    filename: "[name].[hash].bundle.js"
  }
};

2)path

  如果要更改默认的输出路径(即不想在dist目录下生成bundle文件),那么可以通过设置path实现。但要注意,它的值必须是绝对路径,不能是相对路径,如下所示。

module.exports = {
  output: {
    path: __dirname + "/build"
  }
};


四、加载器


  加载器(loader)能在webpack加载模块时对其进行预处理,即对模块的源码进行转换,下面列出加载器的几个比较典型的用途。

(1)将浏览器无法识别的JSX、Sass等语言转换成JavaScript、CSS等语言。

(2)把图像转换成Data URI格式嵌入到JavaScript文件中。

(3)用ES6的import关键字将CSS文件导入到JavaScript中。

1)配置

  加载器不仅需要单独安装,还得在webpack.config.js中配置module字段。下面是一个简单的配置示例,其作用是让file-loader加载器处理四种类型的图像。


module.exports = {
  module: {
    rules: [{
        test: /\.(png|svg|jpg|gif)$/,
        use: [ "file-loader" ]
    }]
  }
};


  module的值是一个对象,包含一个rules属性,记录了模块匹配的规则,而这些规则又会以对象的形式组成一个数组,作为rules属性的值。每条规则必须包含test和use两个属性,前者是一个正则表达式,可设置匹配条件;后者是一个由字符串或对象组成的数组,可指定要使用的加载器。只有当test属性中的条件匹配成功后,才会让use属性中的加载器处理相应的模块。

  接下来将展示加载器的用法,以上面的file-loader为例,首先通过命令将其安装,如下所示。

npm install --save-dev file-loader

  然后创建一个index.js文件,其内容就是引入一张avatar.jpg图像,并将实例化的Image对象添加到页面的<body>元素内,如下所示。

import src from "./avatar.jpg";
var img = new Image();
img.src = src;
document.body.appendChild(img);

  再创建一张index.html页面,引用打包生成的index.bundle.js文件,如下所示。

<body>
  <script src="dist/index.bundle.js"></script>
</body>

  最后执行webpack的打包命令,就会在index.html的<body>元素中添加下面的<img>元素。

<img src="68fd51ab711118f323bdddf6de7a0175.jpg" />

  注意,默认情况下,图像会随着bundle文件一起被放置到dist目录下。这样的话,上述<img>元素将无法读取到图像,得为其src属性加上路径。为了解决该问题,可以利用file-loader提供的配置参数。下面将use属性中的规则修改成对象形式,用options参数记录publicPath选项,即定义图像的发布目录。


module.exports = {
  module: {
    rules: [{
        test: /\.(png|svg|jpg|gif)$/,
        use: [{
            loader: "file-loader",
            options: { publicPath: "./dist" }
        }]
    }]
  }
};


  当一个条件对应多个加载器时,其执行顺序是从右到左。以下面的加载器为例,先执行url-loader,后执行file-loader。


module.exports = {
  module: {
    rules: [{
        test: /\.(png|svg|jpg|gif)$/,
        use: [ "file-loader", "url-loader" ]
    }]
  }
};


  由于目前市面上的加载器有可能无法满足实际需求,因此官方提供了自定义加载器的方法,具体可参考相关文档

2)Babel

  在之前的第2篇中,对Babel做了专门的讲解,现在利用加载器可以将Babel的配置写到webpack.config.js中,接下来将演示在webpack中使用Babel。

  首先安装babel-loader、Babel的核心包以及集合了ES语法的预设,命令如下所示。

npm install --save-dev babel-loader @babel/core @babel/preset-env

  然后在webpack.config.js的module字段中配置规则,如下所示。

module.exports = {
  module: {
    rules: [{
        test: /\.js$/,
        exclude: /node_modules/,
        use: [{
            loader: "babel-loader",
            options: {
              presets: ['@babel/preset-env']
            }
        }]
    }]
  }
};


  rules中的exclude属性定义了忽略的条件,即不会对node_modules目录中的脚本文件执行babel-loader。在babel-loader的presets选项中声明了所使用的预设。当执行打包命令后,就会对下面这样的ES6语法进行编译,转换成低版本的ES语法。

let fn = () => true;


五、插件


  插件能够借助webpack引擎的能力,将自定义的行为注入到webpack的构建流程中,解决加载器无法实现的功能,例如分离打包、压缩文件等。插件不仅能处理模块和编译过的资源,还能监控文件的变化。与加载器一样,插件也可根据特定需求实现自定义,具体可参考官方文档

  插件的配置被放在了plugins字段中,它的值是一个由插件实例组成的数组。接下来将通过html-webpack-plugin来演示插件的用法。

1)配置

  html-webpack-plugin不仅能根据模板生成一个HTML文件,还能自动引入所需的bundle文件,对于那些随着编译而发生名称变化的bundle文件特别有用。

  要使用它,首先需要将其安装,相关的命令如下所示。

npm install --save-dev html-webpack-plugin

  然后在webpack.config.js中声明插件的实例,如下配置所示,在初始化插件时,没有为其传递任何参数。

var HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
  entry: {
    index: "./index.js"
  },
  output: {
    filename: "[name].[hash].bundle.js"
  },
  plugins: [
    new HtmlWebpackPlugin()
  ]
};

  最后执行打包命令,生成的HTML文件如下所示,其中脚本文件的名称包含了一个hash值。


<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Webpack App</title>
  </head>
  <body>
    <script src="index.4ee657c406f9babd171a.bundle.js"></script>
  </body>
</html>


2)自定义模板

  除了上面所使用的默认模板之外,html-webpack-plugin还提供了自定义模板的功能。默认情况下,html-webpack-plugin采用的是EJS模板引擎,声明的加载器是ejs-loader。如果要使用其它模板引擎,那么必须得把相应的加载器添加到配置文件中。

  下面利用EJS模板的语法插入页面标题,首先创建一个template.html模板文件,如下所示。


<!DOCTYPE html>
<html>
  <head>
    <title><%= htmlWebpackPlugin.options.title %></title>
    <meta charset="utf-8" />
  </head>
  <body>
    <div>模板内容</div>
  </body>
</html>

  然后向插件传递两个参数:title和template,前者就是页面标题,后者是模板路径。如此设置之后,就能渲染出所需要的页面了。


module.exports = {
  plugins: [
    new HtmlWebpackPlugin({ 
      title: "模板", 
      template: "./template.html" 
    })
  ]
};


六、模块化


  webpack实现了一套兼容所有模块化方案的机制,这让任意文件皆有可能成为模块,而构建依赖图和按需打包等功能则都由webpack内部完成。

  在webpack中,能够表达模块之间依赖关系的方式有多种,例如下面所列的。

(1)CommonJS规范的require()函数。

(2)AMD规范的define()函数。

(3)ES6标准的import语句。

(4)Sass和Less中的@import语句。

(5)CSS中引用图像的url()函数。

(6)<img>元素用于加载图像的src属性。

相关文章
|
1月前
|
缓存 前端开发 JavaScript
前端性能优化:Webpack与Babel的进阶配置与优化策略
【10月更文挑战第28天】在现代Web开发中,Webpack和Babel是不可或缺的工具,分别负责模块打包和ES6+代码转换。本文探讨了它们的进阶配置与优化策略,包括Webpack的代码压缩、缓存优化和代码分割,以及Babel的按需引入polyfill和目标浏览器设置。通过这些优化,可以显著提升应用的加载速度和运行效率,从而改善用户体验。
58 6
|
1月前
|
缓存 监控 前端开发
前端工程化:Webpack与Gulp的构建工具选择与配置优化
【10月更文挑战第26天】前端工程化是现代Web开发的重要趋势,通过将前端代码视为工程来管理,提高了开发效率和质量。本文详细对比了Webpack和Gulp两大主流构建工具的选择与配置优化,并提供了具体示例代码。Webpack擅长模块化打包和资源管理,而Gulp则在任务编写和自动化构建方面更具灵活性。两者各有优势,需根据项目需求进行选择和优化。
76 7
|
1月前
|
缓存 前端开发 JavaScript
前端工程化:Webpack与Gulp的构建工具选择与配置优化
【10月更文挑战第27天】在现代前端开发中,构建工具的选择对项目的效率和可维护性至关重要。本文比较了Webpack和Gulp两个流行的构建工具,介绍了它们的特点和适用场景,并提供了配置优化的最佳实践。Webpack适合大型模块化项目,Gulp则适用于快速自动化构建流程。通过合理的配置优化,可以显著提升构建效率和性能。
53 2
|
2月前
|
前端开发 JavaScript 开发者
构建工具对比:Webpack与Rollup的前端工程化实践
【10月更文挑战第11天】本文对比了前端构建工具Webpack和Rollup,探讨了它们在模块打包、资源配置、构建速度等方面的异同。通过具体示例,展示了两者的基本配置和使用方法,帮助开发者根据项目需求选择合适的工具。
28 3
|
3月前
|
JSON 前端开发 JavaScript
不会webpack的前端可能是捡来的,万字总结webpack的超入门核心知识
该文章提供了Webpack的基础入门指南,涵盖安装配置、基本使用、加载器(Loaders)、插件(Plugins)的应用,以及如何通过Webpack优化前端项目的打包构建流程。
不会webpack的前端可能是捡来的,万字总结webpack的超入门核心知识
|
2月前
|
前端开发 JavaScript Shell
深入解析前端构建利器:webpack核心概念与基本功能全览
深入解析前端构建利器:webpack核心概念与基本功能全览—
34 0
|
3月前
|
前端开发 开发者
在前端开发中,webpack 作为一个强大的模块打包工具,为我们提供了丰富的功能和扩展性
【9月更文挑战第1天】在前端开发中,Webpack 作为强大的模块打包工具,提供了丰富的功能和扩展性。本文重点介绍 DefinePlugin 插件,详细探讨其原理、功能及实际应用。DefinePlugin 可在编译过程中动态定义全局变量,适用于环境变量配置、动态加载资源、接口地址配置等场景,有助于提升代码质量和开发效率。通过具体配置示例和注意事项,帮助开发者更好地利用此插件优化项目。
89 13
|
4月前
|
前端开发 JavaScript C++
【绝技大公开】Webpack VS Rollup:一场前端工程化领域的巅峰对决,谁能笑到最后?——揭秘两大构建神器背后的秘密与奇迹!
【8月更文挑战第12天】随着前端技术的发展,模块化与自动化构建成为标准实践。Webpack与Rollup作为主流构建工具,各具特色。Webpack是一款全能型打包器,能处理多种静态资源,配置灵活,适合复杂项目;Rollup专注于ES6模块打包,利用Tree Shaking技术减少冗余,生成更精简的代码。Rollup构建速度快,配置简洁,而Webpack则拥有更丰富的插件生态系统。选择合适的工具需根据项目需求和个人偏好决定。两者都能有效提升前端工程化水平,助力高质量应用开发。
50 1
|
4月前
|
JavaScript 前端开发 API
解锁前端开发新境界:Vue.js携手Webpack,打造高效构建流程,你的项目值得拥有!
【8月更文挑战第30天】随着前端技术的发展,模块化与组件化趋势愈发显著。Vue.js 以其简洁的 API 和灵活的组件系统,深受开发者喜爱;Webpack 则凭借强大的模块打包能力成为前端工程化的基石。两者结合,不仅简化了组件编写与引用,还通过模块热替换、代码分割等功能大幅提升开发效率。本文将通过具体示例,展示如何利用 Vue.js 和 Webpack 构建高效、有序的前端开发环境。从安装配置到实际应用,逐步解析这一组合的优势所在。
52 0
|
5月前
|
JSON 前端开发 JavaScript
前端工程化:Webpack配置全攻略
【7月更文挑战第14天】
83 6