认识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...

相关推荐
WeiXiao_Hyy16 分钟前
成为 Top 1% 的工程师
java·开发语言·javascript·经验分享·后端
吃杠碰小鸡32 分钟前
高中数学-数列-导数证明
前端·数学·算法
kingwebo'sZone38 分钟前
C#使用Aspose.Words把 word转成图片
前端·c#·word
xjt_09011 小时前
基于 Vue 3 构建企业级 Web Components 组件库
前端·javascript·vue.js
我是伪码农1 小时前
Vue 2.3
前端·javascript·vue.js
夜郎king2 小时前
HTML5 SVG 实现日出日落动画与实时天气可视化
前端·html5·svg 日出日落
辰风沐阳2 小时前
JavaScript 的宏任务和微任务
javascript
夏幻灵3 小时前
HTML5里最常用的十大标签
前端·html·html5
冰暮流星3 小时前
javascript之二重循环练习
开发语言·javascript·数据库
Mr Xu_3 小时前
Vue 3 中 watch 的使用详解:监听响应式数据变化的利器
前端·javascript·vue.js