webpack

webpack_第1张图片

个人主页:爱吃炫迈
系列专栏:前端工程化
‍座右铭:道阻且长,行则将至

文章目录

  • 认识webpack
  • webpack是什么
  • webpack作用
  • webpack可以打包什么(Vue项目)
  • webpack使用前提
  • webpack如何对我们的项目进行打包的
  • webpack核心
    • 入口(entry)
    • 输出(output)
    • loader
    • 插件(plugin)
    • Mode配置


认识webpack

随着前端的快速发展,目前前端的开发已经变得越来越复杂了:

  • 比如开发过程中我们需要通过模块化的方式来开发
  • 比如也会使用一些高级的特性来加快我们的开发效率或者安全性,比如通过ES6+、TypeScript开发脚本逻辑,通过sass、less等方式来编写css样式代码
  • 比如开发过程中,我们还希望实时的监听文件的变化来并且反映到浏览器上,提高开发效率
  • 比如开发完成之后我们还需要将代码进行压缩、合并以及其他相关的优化
  • 等等

但是对于很多前端开发者来说,并不需要思考这些问题,日常的开发中根本就没有面临这些问题:

  • 这是因为目前前端开发我们通常都会直接使用三大框架来开发:Vue、React、Angular
  • 但是事实上,这三大框架的创建过程我们都是借助于脚手架的,而Vue-CLI、create-react-app、Angular-CLI都是基于webpack来帮助我们支持模块化、less、TypeScript、打包优化等

webpack_第2张图片

webpack是什么

官方解释:webpack is a static module bundler for modern JavaScript applications.

解释:webpack是一个静态的模块化打包工具,为现代的JavaScript应用程序

  • 打包bundler:webpack可以帮助我们进行打包,所以他是一个打包工具
  • 静态的static:我们最终可以将代码打包成最终的静态资源(部署到静态服务器)
  • 模块化module:webpack默认支持各种模块化开发,ES Module 、CommonJS、AMD等
  • 现代化modern:正是因为现代前端开发面临各种各样的问题,才催生了webpack的出现和发展

webpack作用

webpack_第3张图片

webpack可以打包什么(Vue项目)

  1. JavaScript的打包:
    • 将ES6转换成ES5的语法
    • TypeScript的处理,将其转换成JavaScript
  2. CSS的处理
    • CSS文件模块的加载、提取
    • Less、Sass等预处理器的处理
  3. 资源文件img、font
    • 图片img文件的加载
    • 字体font文件的加载
  4. HTML资源的处理
    • 打包HTML资源文件
  5. 处理vue项目的SFC文件.vue文件

webpack使用前提

  1. webpack的运行时依赖Node环境的,所以我们电脑上必须有Node环境
  2. webpack的安装目前分为两个:webpack、webpack-cli

两者关系:

  • 执行webpack命令,会执行node_modules下的.bin目录下的webpack;
  • webpack在执行时是依赖webpack-cli的,如果没有安装就会报错;
  • 而webpack-cli中代码执行时,才是真正利用webpack进行编译和打包的过程;
  • 所以在安装webpack时,我们需要同时安装webpack-cli(第三方的脚手架事实上是没有使用webpack-cli的,而是类似于自 己的vue-service-cli的东西)
// 全局安装
npm install webpack webpack-cli -g 
// 局部安装
npm install webpack webpack-cli -D 
  1. 使用局部的webpack
  1. 创建package.json文件,用于管理项目的信息、库依赖等

npm init

  1. 安装局部的webpack

npm install webpack webpack-cli -D

  1. 使用局部的webpack

npx webpack

  1. 在package.json中创建scripts脚本,执行脚本打包即可

npm run build

image-20230718114509186

  1. 使用全局的webpack
  1. 可以通过webpack进行打包,之后运行打包之后的代码
    • 在目录下直接执行webpack命令:webpack
  2. 生成一个dist文件夹,里面存放一个main.js的文件,就是我们打包之后的文件:
    • 这个文件中的代码被压缩和丑化了
    • 另外我们发现代码中依然存在ES6的语法,比如箭头函数、const等,这是因为默认情况下webpack并不清楚我们打包后的文 件是否需要转成ES5之前的语法,后续我们需要通过babel来进行转换和设置
  3. 是可以正常进行打包的,但是有一个问题,webpack是如何确定我们的入口的呢?
    • 事实上,当我们运行webpack时,webpack会查找当前目录下的 src/index.js作为入口。所以,如果当前项目中没有存在src/index.js文件,那么会报错
    • 当然我们也可以通过配置来制定入口和出口
    • npx webpack --entry ./src/main.js --output-path ./build

webpack如何对我们的项目进行打包的

  1. 事实上webpack在处理应用程序时,它会根据命令或配置文件找到入口文件
  2. 从入口开始,会生成一个依赖关系图,这个依赖关系图会把包含应用程序中所需的所有模块(比如.js文件,CSS文件,图片,字体等)
  3. 然后遍历图结构,打包一个个模块(根据文件的不同使用不同那个的loader来解析)

webpack核心

入口(entry)

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

默认值是 ./src/index.js,但你可以通过在 webpack configuration 中配置 entry 属性,来指定一个(或多个)不同的入口起点。例如:

webpack.config.js

module.exports = {
    entry:'./src/main.js'
}

输出(output)

output 属性告诉 webpack 在哪里输出它所创建的 bundle,以及如何命名这些文件。主要输出文件的默认值是 ./dist/main.js,其他生成文件默认放置在 ./dist 文件夹中。

你可以通过在配置中指定一个 output 字段,来配置这些处理过程:

webpack.config.js

const path = require('path');

module.exports = {
  entry: './path/to/my/entry/file.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'my-first-webpack.bundle.js',
  },
};

在上面的示例中,我们通过 output.filenameoutput.path 属性,来告诉 webpack bundle 的名称,以及我们想要 bundle 生成(emit)到哪里。可能你想要了解在代码最上面导入的 path 模块是什么,它是一个 Node.js 核心模块,用于操作文件路径。

loader

webpack 只能理解 JavaScript 和 JSON 文件,这是 webpack 开箱可用的自带能力。loader 让 webpack 能够去处理其他类型的文件,并将它们转换为有效模块,以供应用程序使用,以及被添加到依赖图中。

webpack的其中一个强大的特性就是能够通import导入任何类型的模块(例如.css文件),其他打包程序或任务执行器的可能并不支持。我们认为这种语言扩展是很有必要的,应为这可以是开发人员能够创建出更准确的依赖关系图

使用loader

  1. 内联方式:在每个import语句中显示指定loader

在引入的样式前加上使用的loader,并且使用!分割

import "css-loader!../css/style.css"

  1. CLI方式(webpack5中不再使用)

  2. 配置方式:在webpack.config.js文件中指定loader

loader 配置方式

配置方式的意思是我们的webpack.config.js文件中写明配置信息:

  • module.rules中允许我们配置多个loader(因为我们也会继续使用其他loader,来完成其他文件的加载)
  • 这种方式可以更好的表示loader的配置,也方便后期的维护,同时也让我们对各个loader有一全局的概览

module.rules的配置如下:

rules属性对应的值是一个数组:[Rule]

数组中存放的是一个个的Rule,Rule是一个对象,对象可以设置多个属性:

  • test属性:用于对resource(资源)进行匹配的,通常会设置成正则表达式(识别那些文件会被转换
  • use属性:对应的值是一个数组:[UseEntry]。UseEntry是一个对象,可以通过对象的属性来设置一些其他属性(定义在进行转换时i,应该使用那个loader
    • loader:必须有一个loader属性,对应的值是一个字符串
    • options:可选的属性,值是一个字符串或者对象,值会被传入到loader中
    • query:目前已经使用options来代替
  • loader属性:Rule.use:[ { loader } ]的简写

loader 从右到左(或从下到上)地取值(evaluate)/执行(execute)。在下面的示例中,从 css-loader 开始执行,以 style-loader 为结束。

webpack.config.js

const path = require('path');

module.exports = {
  entry: './path/to/my/entry/file.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'my-first-webpack.bundle.js',
  },
   module: {
       rules:[
           {
               test:/\.css$/,
               use:[
                   { loader: "style-loader"}
                   { loader: "css-loader" }
               ]
               // 写法2
               //use:[ "style-loader", css-loader" ]
               // 写法三
               //loader: "style-loader", "css-loader"
           }
       ]
   }
};

以上配置中,对一个单独的 module 对象定义了 rules 属性,里面包含两个必须属性:testuse。这告诉 webpack 编译器(compiler) 如下信息:

“嘿,webpack 编译器,当你碰到「在 require()/import 语句中被解析为 ‘.css’ 的路径」时,在你对它打包之前,先 use(使用) css-loaderstyle-loader 转换一下。”

  1. 加载css文件来说,我们需要一个可以读取css文件的loader,这个loader最常用的是css-loader。如果只是使用css-loader来加载css文件,我们会发现这个css在我们的代码中并没有生效(页面没有效果),这是因为css-loader只是负责将.css文件进行解析,并不会将解析之后的css插入到页面中,如果我们希望再完成插入style的操作,那么我们还需要另外一个loader,就是style-loader。

  2. 在我们的开发中,我们可能会使用less、sass、stylus的预处理器来编写css样式,效率会更高。那又该如何处理less文件呢?

    首先,less、sass等编写的css需要通过工具转换成普通的css,然后再处理样式

    module: {
           rules:[
               {
                   test:/\.less$/,
                   use:[
                       { loader: "style-loader"}
                       { loader: "css-loader" },
                       { loader: "less-loader" }
                   ]
               }
           ]
       }
    

    loader特性

    • 支持链式调用。链中的每个loader会将转换应用在已处理过的资源上。一组链式的loader将按照相反的顺序执行。链中的第一个loader将其结果(也就是应用过转换后的资源)传递给下一个loader,以此类推。最后,链中的最后一个loader,返回webpack所期望的JavaScript
    • loader可以是同步的,也可以是异步的
    • loader运行在Node.js中,并且能够执行任何操作
    • 插件(plugin)可以为loader带来更多特性
    • loader能够产生额外的任意文件

插件(plugin)

loader用于转换某些类型的模块,而插件则可以用于执行范围更广的任务。包括:打包优化,资源管理,注入环境变量

想要使用一个插件,你只需要 require() 它,然后把它添加到 plugins 数组中。

  • 你也可以在一个配置文件中因为不同目的而多次使用同一个插件,这时需要通过使用 new 操作符来创建一个插件实例。

webpack.config.js

const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack'); // 用于访问内置插件

module.exports = {
  module: {
    rules: [{ test: /\.txt$/, use: 'raw-loader' }],
  },
  plugins: [new HtmlWebpackPlugin({ template: './src/index.html' })],
};

在上面的示例中,html-webpack-plugin 为应用程序生成一个 HTML 文件,并自动将生成的所有 bundle 注入到此文件中。

  • 多数插件可以通过选项(option)自定义。

举个栗子:使用postcss工具自动添加浏览器前缀

什么是postcss?

postcss是一个可以通过JavaScript来转换样式的工具,这个工具可以帮助我们进行一些css的转换和适配,比如自动添加浏览器前缀,css样式的重置,但是实现这些功能,我们需要借助于postcss对应的插件。

如何使用postcss?

  1. 查找postcss在构建工具中的扩展,比如webpack中的postcss-loader
  2. 选择可以添加你需要的postcss相关插件

webpack.config.js

module: {
       rules:[
           {
               test:/\.css$/,
               use:[ "style-loader", "css-loader", "postcss-loader" ]
           }
       ]
   }

因为postcss需要有对应的插件才会起效果,所以需要配置它的plugin:autoperfixer

module: {
       rules:[
           {
               test:/\.css$/,
               use:[ "style-loader", "css-loader", 
                    {
                        loader: "postcss-loader",
                        options: {
                            postcssOptions: {
                                plugins: [
                                "autoprefixer"
                                ]
                            }
                        }
                     }
                   ]
           }
       ]
   }

我们可以将这些配置信息放到一个单独的文件中进行管理:

在根目录下创建postcss.config.js

postcss.config.js

module.exports = {
    plugins: [
        require("autoprefixer")
    ]
}

webpack.config.js

module: {
       rules:[
           {
               test:/\.css$/,
               use:[ "style-loader", "css-loader", "postcss-loader" ]
           }
       ]
   }

Mode配置

Mode配置选项,可以告知webpack使用相应模式的内置优化:

  • 默认值是production
  • 可选值:none、development、production
选项 描述
development 会将DefinePlugin中的process.env.NODE_ENV的值设置为development,为模块和chunk启用有效的名
production 会将DefinePlugin中的process.env.NODE_ENV的值设置为production,为模块和chunk启用确定性的混淆名称
none 不使用任何默认优化选项

你可能感兴趣的:(前端工程化,webpack,前端,node.js)