认识webpack|webpack作用|webpack配置

webpack说难很难,说简单也简单,难主要是loaderplugin模块

本期文章主要介绍webpack的使用和作用,以后再来聊原理

webpack是目前用的最多的构建工具,它不是个框架,webpack就是个打包工具,给项目做压缩处理,此前我介绍过vitecli,它们也是构建工具或者打包工具。webpack是个老牌的工具,

常见的构建工具有这些:

vite:很新,vue作者打造的

gulp:国内也用的非常多

grunt

rollup:国外用得非常多

cli

webpack是众多构建工具最出色的,功能最强大,用户基数也是最大的,其实cli就是webpack构建的,其实你学一个最新的vite和一个强大的webpack就够了,其他构建工具要用的时候你也一定从容不迫,都是一类型的东西

为什么项目需要打包?

假设我们项目写完了,我们现在需要把他部署到服务器上去,部署服务器上的目的就是别人也可以访问,就是部署到公网上去,我们连接的wifi是局域网,如果都是同一个wifi那都可以访问你的资源,前提是你允许访问,服务器一定是连接了公网的

假设我们的项目完成后有个60M的大小,其实非常大,所以我们希望对代码进行一个删繁就简,去除掉伪代码,比如用于调试的console.log,就算去掉这些东西,也不会节省夺少空间,我们这么做的原因是服务器的资源非常的昂贵。企业稍微做大一点都是自己做一个服务器,比如内网穿透啥的,让它可以连接到外网,运维来管。初创型的公司一般都是租第三方的服务器,一年动辄几十万,上百万。

所以我们需要进行压缩打包处理,这里的打包和360打包是两码事,后者只是换了个文件格式,前者是去除掉伪代码,去掉代码的换行等等,密密麻麻。尽可能地减少服务器资源的浪费。

当我们使用npm包管理工具进行打包npm run build的时候,你会发现你的项目目录下多了个dist文件夹

其实这个项目结构最终就是被转成了htmljscssassets里面都是些jscss文件,我们随便看一个js文件,代码密密麻麻

这个项目我其实并没有用到这么多代码,最后这么多的原因是因为我用了vantUI框架,引入了它的源码,这些代码都是给机器看的

如果没有跨域等的问题,理论上我们是可以直接运行这个index.html文件的,实际上css等资源必须当成服务资源进行返回

体验webpack带来的效果

现在给到一个情景:我们在项目根目录下新建一个public文件夹,里面放一个index.html,然后在根目录下新建一个文件夹srcsrc下新建一个tools文件夹,写一个add.jsadd.js通过ESModule语法引入到src下的main.js,然后在main.js中调用add.js函数,去打印值,最后引入到index.html

模块化引入这里就不过多展示,语法我在node那期文章都讲了:初识node | 模块化 | yrm换源 | nvm切换node - 掘金 (juejin.cn)感兴趣可以看看两种语法的区别,都非常重要

按道理这么做是没问题的,但是浏览器其实是读不懂es6的模块化语法的,以前是这样的,现在更新了,只要在引入的时候加个属性type即可

xml 复制代码
<script type="module" src="../src/main.js"></script>

现在是这样的,浏览器可以读懂模块化语法,我现在就要回到以前,浏览器就是读不懂模块化语法。

这里说浏览器读不懂es6的模块化语法仅仅是为了假设,现在浏览器基本上都可以读懂es6了,但是es7,es8,es9它还是会读不懂

浏览器更新很慢,跟不上es的版本,所以我们有没有一种方法,让浏览器可以读懂新版本的语法

现在我们还是把type="module"给删掉,模拟下就是让浏览器读不懂。
另外我们也把main.js的引入给删掉,因为webpack是可以帮我们背后做一个引入的,用过cli的就清楚,不需要手动引入js。不过vite要引入

这就是webpack的作用了,它可以把es6,es7,es8等高版本js给降级成低版本的语法。当然不全是webpack的作用,它降不了的可以请帮手

配置webpack

先初始化项目

csharp 复制代码
npm init -y

生成package.json,有这个就可以安装其他内容

首先安装webpackwebpack既然是个构建工具,所以我们在生产环境用不上他,我们只在开发环境用,所以是-D

css 复制代码
npm i webpack webpack-cli -D

这个时候项目目录下就会出现node_modules,这个东西就是放你安装的东西的源码的,会比较大。还会有个package-lock.json文件

手动在项目根目录下创建一个webpack.config.js文件。这里是手动配置webpack

其实以后工作中大概率是不会让你去手动配置一个webpack的。那些脚手架已经可以弄得非常完美了。

但是面试官可能上来会问你一句:vue-cli的执行过程是什么?

我们来到webpack的中文文档下,看下webpack的主要内容模块:概念 | webpack 中文文档 | webpack中文文档 | webpack中文网 (webpackjs.com)

这几个模块会了,你就算是熟悉webpack了。loaderplugin会比较难一点

webpack由于是node写的,所以你可以在里面使用node的内置模块,其实vite也是node写的

webpack.config.js

我们来到项目根目录下新建一个webpack.config.js文件,开始配置该文件

先引入path模块,因为要用上path身上的方法

ini 复制代码
const path = require('path')

然后再抛出一个对象,这里面东西比较多,这里的配置都是给webpack看的

css 复制代码
module.exports = {
	mode: 'development', 
    entry: {
        main: './src/main.js',
    },
    output: {
        path: path.resolve(__dirname, './dist'),
        filename: 'js/chunk-[contenthash].js',
        clean: true,
    },
}

先看下mode这里的值就两个,一个development代表代码在生产环境下生效,webpack库考虑的东西会比后者多;另一个production代表开发环境。

再看下entry,告诉webpack这里的文件是入口文件

有入口就有出口outputwebpack会从入口文件读到后传出去,这个过程会对文件做出一系列操作,path.resolve()是将绝对路径进行拼接。我的文章node常用内置模块总结 - 掘金 (juejin.cn)详细讲了这些模块,最后生成的文件就放到这个路径下

filename就是生成的文件放在js文件夹目录内,文件名为chunk后接一串哈希值,[contenthash]是根据文件内容自动生成的值,如果文件内容变了,那么该值也一定会变

clean是自动清理上一次打包的结果,默认值为true,如果你代码改变了再打包一遍,就会生成一个新的文件,因为文件名hash值变了,cleanfalse就会保留下来原来的

哈希值的意义涉及到cdn的缓存问题。一个情景带你理解,之前讲hash路由原理的时候也提过一嘴,就是大厂的服务器一般会在各个省份都有个分服务器,然后为了保证分服务器与总部的服务器保持同步,分服务器就需要看文件名chunk后面的哈希值是否变更,变了就去往总部那里拿一份最新的过来,哈希值的目的就是为了防止这个缓存,让你拿到的文件是旧版本的,而不是最新的

然后输入指令webpack运行

这个时候webpack就读到入口文件了,然后帮你打包按照你的规则放入了dist

这个地方如果你报错,就说明还没有全局安装一个webpack

less 复制代码
npm i webpack webpack-cli -D -G  // -D开发环境 -G全局 安装两个:一个webpack webpack-cli

这个打包后的js文件,如果你细心,你会发现里面还用到了欺骗词法eval,把不属于这里的代码搬到了这里

我们目前做的这些目的都是为了使用webpack可以把main.js放到index.html中生效

但是webpack是有短板的,它只能打包js代码,因此对于index.html它无动于衷。然而,webpack的精髓就是loaderplugin

这两个东西使得webpack异常的强大。

我们来看下loader

loader可以让webpack理解除了js以外的文件

我们再来看下plugin

plugin的能力比loader强,它不仅可以识别除了js之外的语言,它还可以在这个过程中做其他事情,loader能干的plugin也能干

使用这些东西都需要另外安装,比如这里我们让他读懂html,安装一个plugin。这里因为不仅仅是要读到html,还需要将js插入进去,所以要其他功能,就用插件

css 复制代码
npm i html-webpack-plugin -D 

不清楚指令就去百度,什么文件对应什么指令

webpack官方有很多插件,但是并不能百分百满足我们的日常开发需求,还有一些野路子插件,我们可以去node仓库npm网站中搜,如果实在是搜不到你的需求,你就只能自己手搓一个了

安装完了我们现在要去使用,先引入,再用进来,这里用法是new一个,具体插件的用法需要自行查看用法,打造成了函数就得调用它,打造成了构造函数你就得new

css 复制代码
const path = require('path')

module.exports = {
    mode: 'development', 
    entry: {
        main: './src/main.js',
    },
    output: {
        path: path.resolve(__dirname, './dist'),
        filename: 'js/chunk-[contenthash].js',
        clean: true,
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: './public/index.html',
            filename: 'index.html',
            inject: 'body'
        })
    ]
}

filename还是一样,最后生成的html文件名,然后js需要插入到html里面的body

有些js需要植入到head中,所以inject就是提供了两个选项,一个head一个body

好了,现在已经可以让webpack识别html并且把js植入到html中了,已经实现了webpack的作用了,可以去用liver server运行下index.html看控制台是否有打印3

这里的index.html也已经按照你的规则去生成了,并且js插入到了body

如果你打包运行习惯了npm run build而不是原始的webpack我们这里可以来到package.json中去配置一下

scripts中新加一行"build": "webpack",

这样你运行npm run build就是webpack了,其实老版本的webpack这里的值写的是全称webpack --config webpack.config.js

意思就是webpack运行config的这个配置文件,现在新版本只需要写个webpack即可

webpack并不能把所有的es6-es13的代码全给你读懂,不过webpack可以帮你找帮手,让它帮你解析

读懂css

css也是需要安装的,假设我现在src下新建了一个style文件夹,里面放了个index.css样式文件,并且导入到main.js

这里用css不需要做其他事情,刚刚的html用插件是因为还需要插入操作,因此这里用loader去解决css

我们去到官网找css的loader,里面还有lesssass样式,这里我们导入cssstyle-loader,一般用css-loader还会带上style-loader

style就是让css以style标签的形式

css 复制代码
 npm i css-loader style-loader -D

安装完后依旧去webpack.config.js使用它

css 复制代码
module.exports = {
    mode: 'development', 
    entry: {
        main: './src/main.js',
    },
    output: {
        path: path.resolve(__dirname, './dist'),
        filename: 'js/chunk-[contenthash].js',
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: './public/index.html',
            filename: 'index.html',
            inject: 'body',
        })
    ],
    module: {
        rules: [
            {
                test: /\.css$/i,  // $表示后缀
                use: ['style-loader', 'css-loader']  // 顺序不能乱,从右往左读
            }
        ]
    }
}

这里没有写生成到那里,就会默认生成到js中,所以为了模块化,需要单独打包到一个文件中

那就需要再下载一个插件,因为读到css还需要干其他的事情,就是用插件

css 复制代码
npm i mini-css-extract-plugin -D

安装后后引入,再使用

用法看下npm官网mini-css-extract-plugin - npm (npmjs.com),用了正则

javascript 复制代码
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin'); 
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
    mode: 'development', 
    entry: {
        main: './src/main.js',
    },
    output: {
        path: path.resolve(__dirname, './dist'),
        filename: 'js/chunk-[contenthash].js',
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: './public/index.html',
            filename: 'index.html',
            inject: 'body',
        }),
        new MiniCssExtractPlugin({
            filename: 'styles/chunk-[contenthash].css',
        })
    ],
    module: {
        rules: [
            {
                test: /\.css$/i,  // $表示后缀
                use: [MiniCssExtractPlugin.loader, 'css-loader']  // 顺序不能乱,从右往左读
            }
        ]
    }
}

图片

其实是可以读懂图片的,没有配规则的时候,图片资源会默认放到dist文件夹中,命名很乱,也没有一个文件夹去装,如图效果

来到module中配置一个规则,图片的格式就那么几个,这里全部写上

yaml 复制代码
module: {
    rules: [
        {
            test: /\.(png|jpe?g|gif|svg)$/,
            type: 'asset',
            // parser: {  // base64
            //     dataUrlCondition: {
            //         maxSize: 5 * 1024 * 1024, // 1bit 1kb 1Mb
            //     },
            // },
            generator: {
                filename: 'images/[contenthash][ext][query]'
            }
        }
    ]
}

注释掉的地方的效果是给你转成base64的格式,并且放到了js文件中

babel

babel就是webpack找的帮手,babel可以读懂最新的es版本并且编译成低版本的es

Babel 中文网 (nodejs.cn)

假设浏览器读不懂箭头函数的语法,那么babel就可以把箭头函数降级成普通函数

安装babel

bash 复制代码
 npm i @babel/core babel-loader @babel/preset-env @babel/plugin-transform-runtime -D

babel/corebabel的核心代码,babel-loader就是让webpack可以用这个babelpreset-env是个线程转换规则,plugin-transform-runtime是转换async await的插件

然后去到rule再添加一个规则,exclude是把依赖排除在外,这个一定要写

javascript 复制代码
module: {
    rules: [
        {
            test: /\.js$/,
            exclude: /node_modules/,
            use: ['babel-loader']
        }
    ]
}

这还不够,因为你需要向babel指名从es几降到es几,来到根目录配置一个babel.config.js文件

java 复制代码
module.exports = {
    presets: [
        '@babel/preset-env'  // 默认的规则
    ],
    plugins: ['@babel/plugin-transform-runtime'], // babel运行的时候进行转换
}

好了,这个时候,es6就被转成es5了,我之前的add.js写的是箭头函数,去打包后的js中搜不到const add了,倒是变成了function add

有了这个东西,es多新你就用多新,不用担心浏览器读不懂

读懂vue

不用想,webpack肯定也是读不懂vue的

先安装个vue

css 复制代码
npm i vue

现在我用vue的写法去写main.js

src下再新建一个App.vue,随便写点内容

xml 复制代码
<template>
    <div class="wrapper">
        hello world
    </div>
</template>

<script>
    export default {
        
    }
</script>

<style lang="css" scoped>
.wrapper {
    width: 300px;
    height: 300px;
    background-color: black;
    color: white;
    font-size: 20px;
}
</style>

如何让webpack读懂vue呢,先装东西

css 复制代码
npm i vue-template-compiler vue-loader @vue/babel-preset-jsx -D

vue也会涉及到es新语法,所以要用上babel

然后在webpack.config.js中引入并使用它,碰到vue后缀的文件就用vue-loader去读懂它

javascript 复制代码
const { VueLoaderPlugin } = require('vue-loader');

module.exports = {
    plugins: [
        new VueLoaderPlugin(),
    ],
    module: {
        rules: [
            {
                test: /\.vue$/,
                use: 'vue-loader'
            }
        ]
    }
}

读到之后插件会进行解析,最后在babel.config.js中再配置下,碰到vue时用另一个规则去解析vue中的js代码

java 复制代码
module.exports = {
    presets: [
        '@babel/preset-env',  // 默认的规则
        '@vue/babel-preset-jsx'
    ],
    plugins: ['@babel/plugin-transform-runtime'], // babel运行的时候进行转换
}

以上就是完整的vue-cli如何被完整打造出来的,其实就是这样配置的

最后

面试中,webpack会被问到的核心问题主要就是这个三个:

  1. webpack的打包过程,原理是什么
  2. 有自己开发过webpack的插件吗
  3. 有自己开发过webpackloader

这三个问题都很难,第一个问题就需要我们自己手搓一个webpack,也就是用node搭建一个webpack你才能理解它的原理,以后再来详谈这些

本期文章主要带大家认识了下webpack,以及基本的配置,清楚他能给我们带来什么样的作用,其实就是一个打包作用,并且同时可以在帮手babel的作用下给js语法降级,让浏览器可以读懂它

另外有不懂之处欢迎在评论区留言,如果觉得文章对你学习有所帮助,还请"点赞+评论+收藏"一键三连,感谢支持!

本次学习代码已上传至本人GitHub学习仓库:github.com/DolphinFeng...

相关推荐
m0_748256788 分钟前
SpringBoot 依赖之Spring Web
前端·spring boot·spring
web1350858863537 分钟前
前端node.js
前端·node.js·vim
m0_5127446438 分钟前
极客大挑战2024-web-wp(详细)
android·前端
若川1 小时前
Taro 源码揭秘:10. Taro 到底是怎样转换成小程序文件的?
前端·javascript·react.js
潜意识起点1 小时前
精通 CSS 阴影效果:从基础到高级应用
前端·css
奋斗吧程序媛1 小时前
删除VSCode上 origin/分支名,但GitLab上实际上不存在的分支
前端·vscode
IT女孩儿1 小时前
JavaScript--WebAPI查缺补漏(二)
开发语言·前端·javascript·html·ecmascript
m0_748256564 小时前
如何解决前端发送数据到后端为空的问题
前端
请叫我飞哥@4 小时前
HTML5适配手机
前端·html·html5
@解忧杂货铺5 小时前
前端vue如何实现数字框中通过鼠标滚轮上下滚动增减数字
前端·javascript·vue.js