本文转载自微信公众号「前端万有引力」,作者 一川 。转载本文请联系前端万有引力公众号。
1.webpack的基本概念
1.1 webpack是什么?
webpack是一个现代js应用程序的静态模块打包器(module bundler),一种前端资源构建工具。
- 什么是前端资源构建工具?在浏览器中是不认识sass、less、ts等web资源和js高级语法,只有通过webpack这样的构建工具来将它们一一编译成浏览器能够读取的js文件。
- 什么是静态资源打包器?在webpack处理应用程序时,它会递归构建一个依赖关系图,将应用程序需要的所有模块打包成一个或多个bundle。
1.2 webpack可以用来做什么?
webpack作为前端工程师最常用的前端资源构建工具,能够解决很多在开发中的遇到的痛点和难点。
- 可以不依赖后端,解决调用后端接口时的跨域问题
- 在代码改动后自动刷新浏览器,有缓存时也无需清除缓存
- 可以方便解决css和js新特性在各浏览器上的兼容性问题,提高自己的开发效率
- 无需使用额外的打包平台和编写打包脚本,也无需单独对js、css等进行打包压缩
当然,webpack的强大不止这些,它有很多简单方便的配置能够提升你的开发效率。
2. webpack的核心配置
常用的核心配置如下:
- 入口 entry
- 输出 output
- 加载器 loader
- 插件 plugin
- 模式 mode
- 其它配置等
当然,以上列举的是常用的配置,其它的需求可以查找官方文档进行阅读:[https://webpack.docschina.org/concepts/]
2.1 入口 entry
入口(entry)毫无疑问指的是webpack以哪个或哪些文件作为打包的起点,以哪个模块来构建内部依赖图。webpack会根据依赖图去分析各个模块之间的依赖关系,从而进行打包。
- //单文件入口,string形式:打包形成一个chunk,输出一个bundle文件,当然在实际开发中的灵活性不大
- entry:"./src/index.js"
- //多文件入口,array形式:所有文件最终形成一个chunck,输出一个bundle文件
- entry:["./src/index.js","./src/main.js"]
- //多文件入口,object形式:多个入口文件就形成多个chunk,最终输出多个bundle文件,而chunk的名称就是对象的key值.虽然这种方式比较繁琐,但是其扩展性比较强,配置可以重复使用,也可以配合其它配置组合使用。
- entry:{
- index:"./src/index.js",
- main:"./src/main.js"
- }
当然在描述入口的对象的时候,还有许多其它配置属性,具体可以查看文档。
- dependOn: 当前入口所依赖的入口。它们必须在该入口被加载前被加载。
- filename: 指定要输出的文件名称。
- import: 启动时需加载的模块。
- library: 指定 library 选项,为当前 entry 构建一个 library。
- runtime: 运行时 chunk 的名字。如果设置了,就会创建一个新的运行时 chunk。在 webpack 5.43.0 之后可将其设为 false 以避免一个新的运行时 chunk。
- publicPath: 当该入口的输出文件在浏览器中被引用时,为它们指定一个公共 URL 地址。请查看 output.publicPath。
2.2 输出 output
输出(output)显而易见就是告诉webpack在哪里输出打包后的资源bundles,以及如何命名这些输出文件。当然主要文件默认为"./dist/main.js",其它文件则放在"./dist"文件夹中。
- // 打包出口
- output:{
- // 输出文件夹路径
- path:path.resolve(__dirname,"dist"),
- // 文件名
- // filename:"bundle.js"
- // 如果多个入口起点,应当使用占位符确保每个文件具有唯一名称
- filename:"[name].js",
- // 所有资源引入公共路径前缀,用于生产环境需谨慎
- publicPath:"",//编译时,不知道其输出文件的地址,则将其置空,在运行时通过入口起点文件的__webpack_public_path__进行动态配置。
- chunkFilename: "[contenthash:10].chunk.js",
- clean: true, //打包前清空输出目录,相当于clean-webpack-plugin插件的作用。
- /* 当用 Webpack 去构建一个可以被其他模块导入使用的库时需要用到library */
- library: {
- name: "[name]",//整个库向外暴露的变量名
- type: "window"//库暴露的方式
- }
- }
切记:即使可以存在多个 entry 起点,但只能指定一个 output 配置。
2.3 加载器 loader
正如你所知道的,webpack只能解析js和json文件,这是其天生自带的能力。而loader的能力就是让webpack可以去处理其它类型的文件,将其转为webpack能够解析的模块文件js或json,以提供给应用程序使用,生成到依赖图中。
- // 加载器
- loader:{
- // 匹配文件类型,服从正则表达式语法
- test:/\.css/,
- // 定义在转换时,使用到哪些loader,自下而上、自右至左进行处理
- use:[
- "style-loader",//创建style标签,将js文件中的样式资源提取出来,添加到index.html文件的head标签中
- "css-loader",//将css文件转变成commonjs格式加载到js文件中
- {
- loader:"postcss-loader",//css的兼容性处理,切记:需要预先在package.json文件中配置browserlist
- options:{
- postcssOptions:{
- ident:"postcss",
- // postcss-preset-env插件:帮postcss找到package.json中的browserslist配置,根据配置加载指定的兼容性样式
- plugins:[require("postcss-preser-env")()]
- }
- }
- }
- ]
- },
- {
- test: /\.js$/,
- // 注意需要在package.json配置browserslist,否则babel-loader不生效
- // js兼容处理 babel
- loader: "babel-loader",
- // 规则只使用一个loader时推荐写法
- options: {
- presets: [
- [
- "@babel/preset-env",
- // 预设:指示babel做怎么样的兼容处理
- {
- useBuiltIns: "usage",
- //按需加载
- corejs: {
- version: "3",
- },
- targets: "defaults",
- }
- ]
- ]
- }
- }
2.4 插件 plugin
插件plugin:插件其实就是辅助loader去执行范围更广的人物,从打包优化、文件压缩、资源管理以及重新注入环境变量。
- // CleanWebpackPlugin帮助你在打包时自动清除dist文件,学习时使用比较方便
- // const { CleanWebpackPlugin } = require("clean-webpack-plugin"); //从webpack5开始,webpack内置了该功能,只要在ouput中配置clear为true即可
- // HtmlWebpackPlugin帮助你创建html文件,并自动引入打包输出的bundles文件。支持html压缩。
- const HtmlWebpackPlugin = require("html-webpack-plugin");
- // 该插件将CSS提取到单独的文件中。它会为每个chunk创造一个css文件。需配合loader一起使用
- const MiniCssExtractPlugin = require("mini-css-extract-plugin");
- // 该插件将在Webpack构建过程中搜索CSS资源,并优化\最小化CSS
- const OptimizeCssAssetsWebpackPlugin = require("optimize-css-assets-webpack-plugin");
- // vue-loader V15版本以上,需要引入VueLoaderPlugin插件,它的作用是将你定义过的js、css等规则应用到vue文件中去。
- const { VueLoaderPlugin } = require('vue-loader')
- module.exports = {
- module: {
- rules: [
- {
- test: /\.vue$/,
- loader: "vue-loader"
- },
- {
- test: /\.css$/,
- use: [
- // MiniCssExtractPlugin.loader的作用就是把css-loader处理好的样式资源(js文件内),单独提取出来 成为css样式文件
- MiniCssExtractPlugin.loader,//生产环境下使用,开发环境还是推荐使用style-loader
- "css-loader",
- ],
- },
- ],
- },
- plugins: [
- new HtmlWebpackPlugin({
- template:"index.html"
- }),
- new MiniCssExtractPlugin({
- filename: "css/built.css",
- }),
- new OptimizeCssAssetsWebpackPlugin(),
- new VueLoaderPlugin(),
- ]
- }
2.5 模式
模式mode用于告知webpack需要使用对应环境模式下的配置,可以是production、development或者none,当然默认是production。
使用mode模式有两种方式,可以是在配置对象中设置mode选项。
- module.exports = {
- mode:"development"
- }
也可以是在package.json中的cli进行配置:
- webpack --mode=development
官方文档中是这样写的:
选项 | 描述 |
---|---|
development |
会将 DefinePlugin 中 process.env.NODE_ENV 的值设置为 development . 为模块和 chunk 启用有效的名。 |
production |
会将 DefinePlugin 中 process.env.NODE_ENV 的值设置为 production 。为模块和 chunk 启用确定性的混淆名称,FlagDependencyUsagePlugin ,FlagIncludedChunksPlugin ,ModuleConcatenationPlugin ,NoEmitOnErrorsPlugin 和 TerserPlugin 。 |
none |
不使用任何默认优化选项 |
如果要根据 webpack.config.js 中的 mode 变量更改打包行为,则必须将配置导出为函数,而不是导出对象:
- ar config = {
- entry: './app.js',
- //...
- };
- module.exports = (env, argv) => {
- if (argv.mode === 'development') {
- config.devtool = 'source-map';
- }
- if (argv.mode === 'production') {
- //...
- }
- return config;
- };
其它常用配置:
- module.exports = {
- // 解析模块的规则:
- resolve: {
- // 配置 解析模块路径别名:可简写路径。
- alias: {
- "@": path.resolve(__dirname, "src")
- },
- // 配置 省略文件路径的后缀名。默认省略js和json。也是webpack默认认识的两种文件类型
- extensions: [".js", ".json", ".css"], // 新加css文件
- // 告诉webpack解析模块是去找哪个目录
- // 该配置明确告诉webpack,直接去上一层找node_modules。
- modules: [path.resolve(__dirname, "../node_modules")],
- },
- // devServer(开发环境下配置):
- devServer: {
- // 运行代码的目录
- contentBase: path.resolve(__dirname, "build"),
- // 为每个静态文件开启gzip压缩
- compress: true,
- host: "localhost",
- port: 5000,
- open: true, // 自动打开浏览器
- hot: true, //开启HMR功能
- // 设置代理
- proxy: {
- // 一旦devServer(5000端口)接收到/api/xxx的请求,就会用devServer起的服务把请求转发到另外一个服务器(3000)
- // 以此来解决开发中的跨域问题
- api: {
- target: "htttp://localhost:3000",
- // 发送请求时,请求路径重写:将/api/xxx --> /xxx (去掉/api)
- pathRewrite: {
- "^api": "",
- },
- },
- },
- },
- // optimization(生产环境下配置)
- optimization: {
- // 提取公共代码
- splitChunks: {
- chunks: "all",
- },
- minimizer: [
- // 配置生产环境的压缩方案:js和css
- new TerserWebpackPlugin({
- // 多进程打包
- parallel: true,
- terserOptions: {
- // 启动source-map
- sourceMap: true,
- },
- }),
- ],
- },
- };
3参考文章
webpack官方文档
Webpack5.0学习总结-基础篇