webpack核心概念

前言:

        作为一个现代 JavaScript 应用程序的静态模块打包器(module bundler),Webpack 凭借其强大的功能和灵活性,成为了前端开发者的首选工具。今天,我们就来深入探讨 Webpack 的几个核心概念,帮助你更好地理解和使用这个强大的工具。

        webpack官网:点击<<<

1.使用webpack

1.1 初始化项目

        首先我们先要创建一个空的文件夹。

        打开该文件的终端,输入npm init命令创建package.json。输入命令后一直点Enter回车,就可以创建package.json。


        这时候我们就可以开始创建目录了。目录结构如下:

        我们在index.html文件中引入app.js。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<script src="./src/app.js "></script>
<body>
    
</body>
</html>

        common.js文件内容:

export default function(){
    console.log('common模块')
}

        util.js文件内容:

export default function(){
    console.log('util模块')
}

        在app.js中引入两个模块,并调用。

import common from "./components/common";
import util from "./components/util";

common()
util()

        这时候我们运行index.html文件时会发现报错,这时候也必定会报错。遇到报错情况时我们应该冷静分析。

        从报错结果我们可以分析出来,该报错应该会与import有关,其实不然,这是因为浏览器是不支持import,因此这时候我们要去使用webpack。

1.2 安装webpack

        因为webpack是一个工具,我们先是要去安装它。

        输入该命令,装webpack工具的同时,也要将webpack的脚手架一同安装,它可以命令式的执行webpack。-D表示的是开发环境。

1.3 命令式使用webpack

        输入npx webpack ./src/app.js命令,npx是先从本地找到相应的资源,找不到再下载,所以使用npx就可以避免执行命令时编写过长的文件路径。

        构建完之后会生成一个dist文件,注意:我们构建的文件一定是在dist中。可以看到dist文件里面有一个main.js文件。

        main.js里面的内容为:

(()=>{"use strict";console.log("common模块"),console.log("util模块")})();

        刚刚我们在输入命令后,弹出了一行警告。

        该警告的意思是我们没有给它一个环境,是开发环境或者是生产环境。我们这边输入选择开发环境。输入命令npx webpack ./src/app.js --mode development,再构建一次。这时候就没有警告了,再点击main.js,可以看到文件内容发送了变化。这边要注意的是我们的配置文件应该是cmd。

        如果不是的话我们点击旁边的下拉按钮,选择默认配置文件,修改为cmd,其他的会有权限问题。

1.4 配置式使用webpack

        到这一步时,我们可以看到上面的命令式的使用webpack会比较麻烦,需要手动的输入参数来告诉webpack我们需要的打包环境,需要打包的文件等,每次打包都需要输入命令。

        所以webpack就提供了可以将参数配置化,需要在原有的基础上新增一个webpack配置文件,此时的目录如下:

        在项目的根目录新增一个webpack.config.js文件。所有配置我们都在这个文件中,我们给该文件写一个最简单的配置。

module.exports = {
    entry:'./src/app.js',
    mode:'development',
}

        entry和mode都是webpack的核心配置文件,当然也不止这两种。entry表示的是入口文件,也就是需要打包的文件。mode表示的是打包环境,根据打包后的环境来加载不同的打包规则,development是开发环境,production是生产环境。

        然后再使用npx webpack --config ./webpack.config.js执行即可。我们也可以将改命令放入到package.json文件中,让它来帮我们去执行。

        到这里我们就可以去运行了,在终端中输入npm run dev。这时候就打包好了

        在index.html中,使用webpack打包后引入的一定是dist打包后的代码文件,而不是源文件,这时候我们不是直接去引用app.js文件,而是要去引用我们打包后的文件,也就是main.js文件。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<!-- <script src="./src/app.js "></script> -->
 <script src="./dist/main.js"></script>
<body>
    
</body>
</html>

        到这里再去运行一下index.html文件,可以看到已经打印上去了,这样我们就可以正常的使用webpack对我们的js文件进行一个打包。

2.webpack的配置

        2.1 基本配置

entry:表示webpack的入口,指定打包的文件,可以是一个或者多个。

mode:表示打包环境,可设置development或production值。

output:表示输出文件的路径和文件名。

        我们就在webpack.config.js配置文件中添加output这个核心配置,说白了这个配置的作用是打包的文件放在哪里,叫什么名字。

const path = require('path')

module.exports = {
    entry: './src/app.js',
    mode: 'development',
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'main.js',
        clean: true,
    },
}

        output核心配置中有几个参数,path表示输出的路径,因此我们要引入path插件,使用path的resolve方法,它可以去解析路径,就是把路径拼起来。filename表示的是输出的文件名。clean表示的是打包前是否清空之前的dist目录中的文件

2.2 loader

        这个配置非常重要,它可以实现源码的转换,因此它是以源码做为参数的。因为webpack只能支持对js文件和json文件进行打包,其他文件是不支持的,我们就要配置对应的loader对其他文件里面的内容进行解析转化,从而让webpack可以对其他的文件进行打包。 说白了就是将其他文件转换为js文件或者json文件。

2.2.1 处理css

        我们先创建一个css文件夹,在里面添加一个index.css文件,然后写上一些样式,目录如下:

        就比方说随便写一个样式:

.box{
    width: 200px;
    height: 200px;
    background-color: brown;
}

        在index.html中添加一个类名为box的元素。

        我们需要将我们写的样式文件引入到app.js中,注意:我们在使用模块引入css的时候是不需要变量去接收它的,直接import后面接上路径就可以了。

import './css/index.css'

        引入过后我们在终端中输入npm run dev再构建一次,会发现报错了。

        报错的原因刚刚也提到过,这是因为webpack是不支持对css文件进行打包的,因此我们要把css文件转换为js文件,让webpack能够进行打包。

        我们就需要通过loader来将css文件转换为js文件,处理css需要用到css-loader和style-loader.

        css-loader的作用是将css文件转换为js文件。

        style-loader的作用是将css文件转换的js文件引入到项目中。

        我们需要安装这两个命令:

npm i css-loader style-loader -D

        这时候我们就可以在webpack.config.js配置文件中来配置loader,我们需要在module中进行配置,代码如下:

const path = require('path')

module.exports = {
    entry: './src/app.js',
    mode: 'development',
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'main.js',
        clean: true,
    },
    module:{
        // 配置loader解析css文件
        rules:[
            {
                test: /\.css$/,
                use:['style-loader','css-loader']
            }
        ]
    }
}

        注意点:test后面接的是正则表达式,use后面loader的加载顺序,它是从后往前执行的,因此先执行的应该写在后面,这点要记住,很容易记混。

        配置完之后,我们在终端中再使用npm run dev命令构建一次,可以看到并没有报错。

        这时候我们就可以运行index.html文件了,可以看到样式正常的渲染到页面上了。

        因此,在处理css资源时,css-loader和style-loader两者缺一不可。

2.2.2 处理sass和less

        首先我们先在css文件目录里面创建一个sass文件和一个less文件。

        注意:因为sass文件它的写法是不可忍受的,因此后面出了个scss,我们这边使用的是scss。

        然后再在index.html文件中创几个盒子,在less和sass文件中分布添加样式。注意:less文件在保存时会直接生成一个css文件,当该目录有同名的css文件会将其覆盖,因此我们这边在less中添加样式保存后,我们要去css里面还原我们之前的样式。

        在app.js中引入我们刚刚创的文件。

import './css/index.less'
import './css/index.scss'

        跟css的情况同理,webpack也不认识less的文件,sass文件,构建后它还是会报错。

        这时我们需要同时安装less和sass,以便能够将less和sass编译成css,然后对css进行操作,输入以下命令安装less和sass:

npm i less less-loader sass sass-loader -D

        less-loader/sass-loader的作用是将less/sass文件转化为css,然后通过css-loader和style-loader再进行接下来的操作。

        less/sass的作用是给我们的代码提供一个less/sass的运行环境。

        安装完之后我们就需要在配置文件中去配置loader。配置代码如下:

            // 处理css文件
            {
                test: /\.css$/,
                use:['style-loader','css-loader']
            },
            // 处理less文件
            {
                test: /\.less$/,
                use:['style-loader','css-loader','less-loader']
            },
            // 处理sass文件
            {
                test: /\.s[ac]ss$/,
                use:['style-loader','css-loader','sass-loader']
            }

        因为刚刚说了loader的加载顺序是从后往前执行的,这里我们需要先将less/sass文件先转换为css文件,因此应该写在最后面。

        sass需要写成s[ac]ss的形式,这表示的样式是这里既可以是sass文件,也可以是scss文件。

        然后我们在终端中构建一次,再运行index.html文件可以看到less文件和sass文件里的样式都渲染到页面上了。

2.2.3 处理图片

        首先我们在项目中的src下新建一个images文件夹,在其中引入图片。

        然后在index.html文件中添加一个div,在给该div添加样式和背景图片。

        在配置文件中处理图片。

            {
                test:/\.(jpe?g|png|gif|webp|svg)$/,
                type:'asset'
            }

        因为图片的后缀名有很多,我们都需要考虑到,在处理图片时我们不需要使用到loader,我们只需要配置它的类型,这边我配置了一个asset类型。可配置的类型如下:

        我们还可以给图片配置一个parser。代码如下:

            {
                test:/\.(jpe?g|png|gif|webp|svg)$/,
                type:'asset',
                parser:{
                    dataUrlCondition:{
                        maxSize: 10 * 1024
                    }
                }
            }

        这里maxSize的意思是超过10k就作为图片引入,否则转换为Base64。

        上面可以看到,图片打包后输出目录与main.js在同一目录,如果想把图片打包放到dist/static/images目录下,那么就要使用到generator字段。代码如下:

           {
                test:/\.(jpe?g|png|gif|webp|svg)$/,
                type:'asset',
                parser:{
                    dataUrlCondition:{
                        maxSize: 10 * 1024
                    }
                },
                generator:{
                    filename:"static/images/[hash][ext][query]"
                }
            }

        generator中的filename指定了存放的目录

        [hash]:表示hash值,后面可携带自定义位数。

        [ext]:原文件扩展名

        [query]:添加之前的query参数

2.2.4 处理字体图标

        跟上面一样,在src下新建一个fonts文件夹,然后我们就可以去阿里巴巴矢量图标库任意下载一个图标,将下载好的图标放到fonts文件夹中,将下载的iconfont.css在app.js中引入,并在index.html文件中新增标签。

import './fonts/iconfont.css'
<span class="iconfont icon-new"></span>

        在终端中构建,运行index.html就可以看到字体图标已经渲染上去了。

        如何没生效的话,可以去检查下iconfont.css中的路径是否对的上。

        最后在配置文件中新增配置,代码如下:

            // 处理字体图标文件
            {
                test:/\.(ttf|woff|woff2)$/,
                type:'asset/resource',
                generator:{
                    filename:"static/font/[hash][ext][query]"
                }
            }

        asset/resource 能够将资源原封不动的输出到指定位置。 

        在webpack早期版本中,所有webpack不支持打包的文件都要用到loader,在webpack5中把一些常用的资源,将它们给内置了,不要我们再去手动下载并配置loader了。

2.2.5 处理css兼容性

        兼容性问题一直是前端比较头疼的问题,但是在webpack中可以通过loader,将一些比较新的css语法能够在低版本的浏览器中使用,就需要下载postcss-loader,但这个loader还依赖postcss和postcss-preset-env,因此需要安装三个模块。命令如下:

npm i postcss-loader postcss postcss-preset-env -D

        在配置文件中修改webpack的配置如下:

            // 处理css文件
            {
                test: /\.css$/,
                use:[
                    'style-loader',
                    'css-loader',
                    {
                        loader:'postcss-loader',
                        options:{
                            postcssOptions:{
                                plugins:['postcss-preset-env']
                            }
                        }
                    }
                ]
            },
            // 处理less文件
            {
                test: /\.less$/,
                use:[
                    'style-loader',
                    'css-loader',
                    {
                        loader:'postcss-loader',
                        options:{
                            postcssOptions:{
                                plugins:['postcss-preset-env']
                            }
                        }
                    },
                    'less-loader'
                ]
            },

        处理sass同理,要在将less/sass文件转换为css文件后在处理。

        除了以上配置外,还需要在package.json中新增"browserslist":["ie >= 7"],去兼容IE浏览器。

        我们可以在index.css里面加一个display:flex测试一下,打包后可以看到做了兼容性处理。

2.2.6 处理js兼容性

        es6推出了许多新的语法,刚刚推出了的时候,浏览器这边不可能直接就去兼容新语法,它需要时间去兼容。但是在工程化项目中是可以放心大胆的使用的,可以通过loader,可以将js语法在较低的浏览器版本中使用,主要是通过babel,同时也要去安装三个模块,一个loader,一个核心库,一个虚设,分布就是babel-loader、@babel/core、@babel/preset-env,安装命令如下:

npm i babel-loader @babel/core @babel/preset-env -D
  •  babel-loader:将es6的语法转换为es5。
  • @babel/core:Babel编译的核心包。
  • @babel/preset-env:Babel编译的预设,可以理解为Bable插件的超集。

        安装完后在配置文件中新增loader配置如下:

            // 处理js兼容问题
            {
                test:/\.js$/,
                exclude:/node_modules/,
                use:['babel-loader']
            }

        要使用exclude去排除node_modules下的文件,不排除的话,它会对node_modules下的所有文件转换为低版本的js,node_modules中有大量的文件,这些代码也不需要我们去转换,因此我们要去排除node_modules。

        到这一步还没有完,@babel/preset-env才是主要转换代码的东西,为了后面方便的修改,在项目的根目录新建一个babel.config.js配置文件,这个是babel专用的配置文件,配置代码如下:

module.exports = {
    presets:['@babel/preset-env']
}  

        如何我们就可以测试一下,在开始创建的common.js文件中添加一个剩余参数运算符,然后打印,代码如下:

export default function(...arr){
    console.log('common模块',arr)
}

        然后在app.js文件中任意添加参数,代码如下:

common('html','css','js');

        构建之后运行index.html,打开控制台。

        说白了babel-loader就是将高版本的js语法转换为低版本的js语法,这样我们写代码时候就可以放心的去写,不用担心兼容性的问题。

2.3 Plugin

        刚刚的loader就是将webpack不支持的文件转换为js文件,这样webpack就可以去对这些文件进行打包。

        loader使webpack能够转化文件,而plugin则使webpack能够拥有压缩、提取等强大的功能。

2.3.1 提取css为单独的文件:

        loader处理的css文件,是将其转换为js文件直接插入到html中,不是用引入链接的方式,这样在访问页面时从解析js到解析完成会有一个突然出现的效果,会影响用户体验。

        可以通过MiniCssExtractPlugin插件将css提取到单独的文件中。

        相关文档:HtmlWebpackPlugin

        首先我们要去安装这个插件,命令如下:

npm i mini-css-extract-plugin -D

        安装好之后,在配置文件中引入我们安装好的插件。代码如下:

// 引入抽离css插件
const MiniCssExtractPlugin = require('mini-css-extract-plugin')

        然后将我们之前配置的所有style-loader换成MiniCssExtractPlugin.loader,style-loader的作用是将css文件转换的js文件引入到我们的项目中,这时候我们不需要它去引入了,而是将转换的js文件抽离成一个文件。代码如下:

            // 处理css文件
            {
                test: /\.css$/,
                use:[
                    MiniCssExtractPlugin.loader,
                    'css-loader',
                    {
                        loader:'postcss-loader',
                        options:{
                            postcssOptions:{
                                plugins:['postcss-preset-env']
                            }
                        }
                    }
                ]
            },

        less与sass同理,全部换为MiniCssExtractPlugin.loader。还需要在module外面写一个plugins,它是一个数组,可以传多个插件。如下所示:

        在里面添加一个new MiniCssExtractPlugin,参数是一个对象,对象中添加地址。代码如下:

plugins:[
        // 把css抽离成单独的文件
        new MiniCssExtractPlugin({
            filename:'static/css/app.css'
        })
    ]

        再在终端中构建,可以看到在dist文件夹下的static文件夹,我们就成功将css提取到了单独的文件里了。

        但是在index.html还需要我们手动引入。

<link rel="stylesheet" href="./dist/static/css/app.css">
2.3.2 自动引入js和css

        上面打包后,不管是将js还是将css打包成单独的文件,在index.html中还需要手动的引入相应的资源,如果修改了webpack打包的js和css文件的路径,那么index.html也需要做相应的修改,比较麻烦。

        以上问题可以通过HtmlWebpackPlugin插件解决。

        安装该插件,命令如下:

npm i html-webpack-plugin -D

        跟上面逻辑是差不多的,安装完之后引入刚刚安装的文件。代码如下:

// 引入自动引入插件
const HtmlWebpackPlugin = require('html-webpack-plugin')

        在plugins中添加自动引入css文件插件,代码如下:

    plugins:[
        // 把css抽离成单独的文件
        new MiniCssExtractPlugin({
            filename:'static/css/app.css'
        }),
        // 自动引入css文件插件
        new HtmlWebpackPlugin({
            template:path.resolve(__dirname,'index.html')
        })
    ]

        然后再在终端中构建,打包后,可看到dist下有一个index.html文件,同时会帮我们引入相关资源,这时可以访问这个新的index.html来查看效果了。

2.3.3 压缩css

        在配置文件中将打包环境切换为生产环境。代码如下:

mode: 'production',

        再打开我们打包好的css文件。

        里面有大量的空格和空行,这都是不需要的,需要用webpack将其抽离到极致,上线后的css应该是压缩后的。

        同样的,使用 CssMinimizerWebpackPlugin 这个插件能够将css压缩为一行,减少代码体积。

        安装这个插件,命令如下:

npm i css-minimizer-webpack-plugin -D

        然后引入我们下载好的插件,代码如下:

const CssMinimizerWebpackPlugin = require('css-minimizer-webpack-plugin')

        再在plugins中实例化css压缩插件。代码如下:

        // 实例化css压缩插件
        new CssMinimizerWebpackPlugin()

        只需要new一下就搞定。我们再在终端中构建一次,再返回到打包的css文件中,可以看到此时被压缩成了一行代码。

        2.3.4 自动清空打包目录

        每次打包的时候,打包的目录都会遗留上次打包的文件,为了保持目录的纯净,我们需要在打包前将打包目录清空。

        这里使用到了 clean-webpack-plugin 插件来实现

        安装插件,命令为: 

npm i clean-webpack-plugin -D

        引入我们安装好的插件,注意有个细节,引入时要用花括号包起来了。代码如下:

const { CleanWebpackPlugin } = require('clean-webpack-plugin')

        在plugins中实例化清除构建插件。代码如下

        然后在终端中构建,我们也看不出有什么变化,这个插件的作用就是在打包前将打包目录清空,我们也可以手动清空一下,再构建一次,构建完之后文件仍然打包了。

3.小结

        通过本章博客希望对您有所帮助,对webpack有所理解。上面通过处理各种资源来介绍 webpack 的配置使用,但只介绍了其中一部分,更多的 loader,plugins 等使用方法还是得到官方文档查询。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值