webpack入门—基本的配置选项介绍

前言

webpack这个打包的工具对于很多的开发者来说肯定是很熟悉了,这里介绍一下它的基本配置,虽然以后它可能会被替代,但是就算是被替代它也是经典的打包工具了(这里分享的均是打包src文件夹下面的文件并且装包的时候都需要初始化一个package.json文件来管理下载的包)。

安装与运行

安装和常见命令:

安装webpack之前先安装一下node,在官网中,node会存在两种下载的方式(LTS版本:长期支持的版本,推荐大多数用户去下载)(current版本:当前版本, 当前最新的补丁),因为webpack是基于node来开发的(node下载成功会自动安装npm的工具)

// 1.该工具表示在命令行的窗口可以执行webpack的命令,-g为全局安装,使其可以在任意
// 的目录下去执行webpack
npm install webpack webpack-cli -g


// 2.表示本地安装,全局安装会使项目中的webpack锁定为某一个版本,如果使用不同的
// webpack版本的项目里面,可能会存在构建失败,在团队中如果不了解在全局安装的
// 话,也会出现构建问题
npm i webpack webpack-cli --save-dev

//  3.以绝对路径的方式显示用户当前的工作目录
pwd

//  4.查看webpack-cli中可以使用那些命令
npx webpack --help



// 5.保存文件之后,会自动的将需要打包的文件进行打包
npx webpack --watch

// ...命令还有很多,需要了解更多可以去webpack的官网学习

单文件打包的基本配置

流程: 使用webpack打包模块化以后的应用程序,webpack会生成一个可以部署的dist目录并将打包好的内容放置在这个目录里面,将这个目录里面的内容部署到服务器上,那么浏览器就能够正常访问服务器上的网站和资源了。

// 6.该文件名不可以随便写,因为该文件是webpack自动读取的,然后该文件是运行在
// nodejs里面,所以定义模块的时候需要使用nodejs里面的CommonJS的模块
    

    // 7.path设置的时候需要设置为绝对路径
    const path = require('path')
    
    // 8.安装的插件需要引入才能使用,因为常量为大写字母开头,所以表示
    //   它是一个构造函数或者是一个类
    const HtmlWebpackPlugin = require('html-webpack-plugin')
    
    // 9.将需要打包的css文件合并,使其单独生成一个css的文件
    const MiniCssExtractPlugin = require('mini-css-extract-plugin')
    

    // 10.将打包生成的css文件进行压缩
    const CssMinimizerWebpackPlugin = require('css-minimizer-webpack-plugin')

    module.exports = {
        // 11.指示webpack应该使用哪个模块,来作为构建应用的入口。
        //    进入入口起点后webpack会找出哪些模块和是入口起点的
        //    直接或者间接的依赖,并将其打包到一起,默认的入口文
        //    件为./src/index.js
        entry: "./src/index.js", 
    
        // 12.告知webpack如何向硬盘写入编译文件
        output: {
        
            // 13.打包后的文件名叫什么
            filename: "main.js",
            
            // 14.表示获取到当前文件所在的真实路径,然后将其解析
            //    到指定的路径下面
            path: path.resolve(__dirname,'./dist'),
            
            // 15.每次打包的时候先会清空dist里面的内容
            clean: true,
            
            // 16.定义资源模块的文件名,也可以设置路径,
            //    [contenthash]:系统默认生成文件名的方
            //    法,它会根据文件的内容去生成一个hash的
            //    字符串,[ext]表示使用原来的扩展名
            assetModuleFilename: 'images/[contenthash][ext]' 
        },

        // 17.如果不配置(指定当前的构建环境),打包的时候会发出
        //    警告,development为开发模式
        mode: 'development', 

        // 18.在开发模式下追踪代码,可以将编译后的代码映射回原始
        //    代码(增强代码调试过程)
        devtool: 'inline-source-map',
    
        // 19.plugin表示插件的意思,后面加上s表示可以引入多个插件,
        //    其次,插件的使用需要先引入,然后使用new关键字去实例化,
        //    插件的参数就是一个配置对象(配置即可)
        plugins: [
        
            // 20.该插件可以完成html页面的自动化的生成(如果不配置,
            //    外部的index页面和生成的index页面是没有关系的)
            new HtmlWebpackPlugin({
                
                // 21.以那个文件为模板来生成文件
                template: "./index.html", 
                
                // 22.输出的文件的文件名
                filename: "app.html",
                
                // 23.输出的文件中生成的JS文件存放在那个body里面
                inject: "body" 
                
                // 需要打包那些entry中的那些入口文件(chunk)
                
                // 这里假设配置的入口文件有三个main.js、main2.js
                // 和main3.js,经过下面的配置之后就不会打包main3.js
                // 这个文件了
                chunks:['main.js', 'main2.js']
            }),

            new MiniCssExtractPlugin({
                // 24.输出的文件的文件夹和文件名
                filename: 'styles/[contenthash].css', 
            }),
        ],

        // 25.webpack-dev-server插件会提供一个基本的web服务器,具
        //    有实时重加载的功能(但是其没有输出任何的物理文件,只是
        //    将其打包后的文件放在了内存之中)
        devServer: {
        
            // 26.指明其指向的物理路径,使其作为server的根目录
            static: './dist'
        }, 
        
        // 27.设置不同文件类型的模块
        module: {
        
            // 28.通过设置规则去加载不同类型的文件(rules配置项是一个数组,
            //    这个数组的元素是一个配置对象,每一个配置对象对应一种解析
            //    的规则)
            rules: [
                {
                    // 29.test后面书写正则来定义加载的文件类型,如果需要用
                    //    到.号需要使用\将其转义一下,因为.号在正则之中有特
                    //    殊含义
                    test: /\.png$/, 
                    
                    // 30.type用于匹配模块,它防止了 defaultRules 和它们的
                    //    默认导入行为发生
                    // 31.resource:发送一个单独的文件并导出 URL
                    type: 'asset/resource',
                    
                    // 32.用来定义加载的文件的名字和路径,和上面output里面的
                    //    assetModuleFilename作用是一样的,但是这里面定义的
                    //    优先级高于上面的
                    generator: {
                        filename: 'images/test1.png'
                    }, 
                },

                {
                    test: /\.svg$/, 
                    
                    // 33.inline:导出一个base64资源的 data URI
                    type: 'asset/inline' 
                },

                {
                    test: /\.text$/,
                    
                    // 34.source:导出资源的源代码
                    type: 'asset/source' 
                },

                {
                    test: /\.svg$/,
                    
                    // 35.asset:通用资源类型:在导出一个 data URI 和发送一个
                    //          单独的文件之间自动选择(默认情况下小于8kb的
                    //          文件会被视为inline模块类型)
                    type: 'asset',
                    
                    // 36.解析器
                    parser: {
                    
                         // 37.设置文件路径的状态
                        dataurlCondition: {
                            
                            //  38.默认情况下文件大小不能超过
                            //     8 * 1024 (8M)
                            maxSize: 4 * 1024 * 1024
                        },
                    }, 
                },

                {
                    // 39.在css-loader里面,定义规则中的test属性会识别
                    // 那些文件需要被转换
                    test: /\.css/,
                    
                    // 40.use属性会在定义转换的时候,需要使用那个loader
                    //    来转换,如果需要使用多个loader的情况需要用数组
                    //    将其包裹起来,并且执行的时候是从右往左执行的,
                    //    支持链式调用 
                    
                    // 41.style-loader用于将解析后的css样式渲染到页面的
                    // head里面的style标签里面的
                    use: ['style-loader','css-loader'], 
                    
                    // 42.因为将样式单独的抽离出来,那么style-loader就没
                    //    有用了,需要使用MiniCssExtractPlugin.loader来
                    //    代替
                    use: [MiniCssExtractPlugin.loader,'css-loader'], 
                },

                {
                    // 43.如果存在不支持ES6语法的浏览器,打包之后运行会出
                    //    现报错,所以需要使用babel-loader来完成ES6、5的
                    //    适配
                    test: /\.js$/,
                    
                    // 44.使其不包括那个里面的文件,因为node_modules里面
                    //    的JS是不需要babel去解析的
                    exclude: /node_modules/, 
                    use: {
                        // 45.babel-loader:在webpack里面用来解析ES6
                        loader: 'babel-loader',  
                        
                        // 46.配置参数
                        options: {
                        
                            // 47.添加一些预设(@babel/preset-env
                            //    为babel预设,是一组babel插件的集合)
                            presets: ['@babel/preset-env'],
                            
                            // 48.如果出现报错为:regeneratorRuntime is
                            //    not defined,表示这个函数是webpack生成
                            //    的辅助函数,用来兼容async和await的语法,
                            //    如果出现这个报错可能是未能正确配置babel,
                            //    需要安装@babel/runtime(包含
                            //    regeneratorRuntime,运行时需要)和
                            //    @babel/plugin-transform-runtime这两个
                            //    插件,如果没有async和await报错的话,不要
                            //    随意使用这个插件,存在问题
                            plugins:[
                                [
                                     // 49.编译时需要,会在需要
                                     //    regeneratorRuntime的地方自动
                                     //    require导入包
                                    '@babel/plugin-transform-runtime'
                                ],
                            ],
                        }, 
                    },
                },
            ], 
        }, 

        // 50.可选优化的配置 
        optimization: {
            
            // 51.默认的压缩工具
            minimizer: [
            
                // 52.使用这个插件需要将模式(mode)改为生产模式(production)
                new CssMinimizerWebpackPlugin() 
            ], 
        }, 
    }

代码的分离

    const path = require('path')







    module.exports = {

    
        // 53.问题:如果入口文件中包含一些重复的代码,重复的代码都会引入到
        //       各自的文件之中,造成代码的重复从而占用更多的空间(简单的
        //       解决方法有两种)
        


        // 注意:配置多个入口的文件(加载多个文件到打包的页面上的时候)的时
        //       候需要使用对象,但是出口如果只有一个的话,会出现报错: 
        //       Multiple chunks emit assets to the same filename(说明
        //       需要设置多个出口)
        entry: {
            // 将共有的文件进行抽离出来(方法一):
                index: {
                // 这里是引入单个文件的写法,如果需要将多个文件
                // 作为入口文件,需要用到数组,然后文件解析的顺
                // 序是从左到右依次解析
                    import: "./src/index.js",
                // 会将重复的文件给一个名字
                    dependOn: 'shared'
                },

                // 这里表示的是多个入口文件的打包
                index02: {
                    import: "./src/index02.js",
                    dependOn: 'shared'
                },
                
                // 当上面的文件中存在loadsh的这个文件的时候,将其抽离出来
                // 并定义为shared
                shared: 'lodash' 

            // 使用webpack内置的插件split-chunks-Plugin(方法二):需要
            // 在optimization的优化配置中去写一个splitChunks,内容为
            // chunks:'all'
                index: "./src/index.js",
                index02: "./src/index02.js"
        },

        optimization: {
            // 方法二
            splitChunks: {
                chunks: 'all',
            }
        }, 
    }

打包与缓存

缓存: 然而获取资源比较损耗时间,所以浏览器会使用缓存使网站加载的速度更快,当dist文件夹被部署到服务器上后只会修改它的内容,并不会修改文件名,浏览器可能会认为你没有更新,就会使用它缓存的版本,以此会出现问题。

基本配置:

    const path = require('path')







    module.exports = {

        entry: { 
            index: "./src/index.js",
            index02: "./src/index02.js"
        }, 

        output: { 
        
            // 54.将JS文件打包到一个目录之中(配置出口文件即可)
            // [name]可以拿到入口里面的文件名(chunk的key的名字)
            // [contenthash]表示文件名会随着内容的变化而变化
            // :6表示hash值文件名长度的限制
            filename: "Script/[name].[contenthash:6].js", 
        },

        optimization: {
            splitChunks: {
            
                // 55.缓存组:可以将第三方的插件(都存放在node_modules
                //         这个文件夹里面)打包缓存在浏览器中
                cacheGroups: {
                    vendor: {
                        // 只解析这个文件夹里面的内容
                        test: /[\\/]node_modules[\\/]/, 
                        name: 'vendors',
                        // 对那些chunks进行处理
                        chunks: 'all'
                    }
                } 
            }
        }, 
    }

环境的切换

    // 56.如果需要消除webpack.config.js在生产环境和开发环境中的差异,
    // 可以使用环境变量来帮忙,
    

     // 其中有一个参数为env,参数是一个对象,里面存在一个production
     // 的属性,如果是开发环境,其值为true,否则为false,但是想要使用
     // 这个参数的话需要将module.exports转换为一个函数
    module.exports = (env) => {
        // 在这个函数的内部返回webpack的配置对象
        return { 
            entry: { 
                index: "./src/index.js",
                index02: "./src/index02.js"
            }, 
    
            output: { 
                // 57.设置公共的路径,可以通过这个来指定所有资源的基础路径
                publicPath: 'http://localhost:8000' 
            },
    
            // 58.生产环境可以压缩,开发环境并不能压缩代码
            mode: env.production ? 'production' : 'development',
        }
    }

source-map详解(代码调试)

// 59.注意:生产环境一般不会开启sourcemap的功能,在开发环境中通过
//       devtool配置项开启sourcemap的功能
// 1.通过编译后生成的文件和sourcemap的文件,可以反编译出源码,
//   也就是说线上产物如果有sourcemap文件的话,就有可能存在暴露源码的风险
// 2.sourcemap文件的体积相对巨大,这跟我们生产环境准求有所区别
//  (生产环境追求更小更轻的打包文件)

module.exports = {
    // 取值1:默认情况下source-map的值是eval,会帮我们我们准确锁定
    //        代码的位置,并且会自动在文件的后面自动生成一个sourceURL
    //        的内部地址
    devtool: 'eval', 
    

     // 取值2:会生成一个sourceMap的文件,在生成的文件之中的小面会有
     //        注释说明这个文件在哪里,这个文件就是eval后面生成的那个
     //        文件,所以也会准确锁定代码的位置
    devtool: 'source-map',
    
     // 取值3:跟第二个的区别在于不会生成注释,文件与生成的文件不会
     //        存在关联,不会锁定代码的位置了
    devtool: 'hidden-source-map',
    
     // 取值4:跟第二个的区别在于不会生成sourceMap的文件,但是会生成
     //        注释,其格式是dataUrl的base54,会锁定代码的位置
    devtool: 'inline-source-map',
    
     // 取值5:跟第四个的区别在于不会生成注释,会直接把格式是dataUrl
     //        的base54的信息跟在eval的后面 
    devtool: 'eval-source-map',
    
     // 取值6:会生成sourceMap的文件,但是这个文件里面不存在列的信息,
     //        会准确锁定代码的位置
    devtool: 'cheap-source-map',
    
     // 取值7:会生成sourceMap的文件,但是这个文件里面不存在列的信息,
     //        类似于babel解析的source-map混进来以后也会准确锁定代码
     //        的位置,但是上一个会出现代码识别行数的问题(所以推荐在
     //        开发环境下使用) 
    devtool: 'cheap-module-source-map',
}

devServer详解

说明: 开发环境中,需要启动一个web的服务来模拟用户的访问,以此读取我们打包后的产物,从而观测我们的代码在客户端的表现,devServer配置项就可以做到这样的功能

安装:

npm i webpack-dev-server -D

基础配置:

// 60
const path = require('path')
 
module.exports = {

    devServer: {
        // 指向当前服务的物理路径
        static: path.resolve(__dirname,'./dist'),
        


        // 是否在服务器端进行代码压缩,使其在数据传输的过程中,
        // 可以减少传输的数据大小(只有true才压缩)
        compress: true,
        
        // 配置服务的端口号
        port: 3000,
        
         // 添加响应头,对资源的请求和响应打入一些标识和标志,
         // 便于做一些安全的规范或者方便发生异常之后做请求的链路追踪
        headers: {
            // 这些信息是可以在浏览器中显示的
            'X-Access-Token': '123456' 
        },

        // 代理服务器(用来做跨域服务的)
        proxy: {
            '/api': 'http://localhost:3000'
        },

         // 将服务的协议改为https,默认使用自签名的证书,会让所有浏览
         // 器知道这个是不安全的,会弹出警告
        https: true
        
         // 默认自带https的证书,可以访问到页面,在域名的右边会存在不
         // 安全的字样
        http2: true

        // 在使用不同的路由模式的时候会出现的问题(在框架中)
        historyApiFallback: true,

         // 配置一个服务器,配置完成之后就可以通过一个域名来访问自己
         // 配置的服务器了
        host: '0.0.0.0',
    },
}

页面的部分刷新

// 61
module.exports = {


    devServer: {
         // 开启模块热替换(webpack默认存在的配置),这样在服务器端中,
         // 如果我修改页面的内容然后保存,服务器上页面是会自动更新的,
         // 不需要再去刷新浏览器才能看到效果了
        hot: true,
        


         // 当页面被修改的时候,会自动的帮助我们编译并刷新页面
        liveReload: true
    }
}

webpack的代码规范约束

说明: 代码规范的约束的话使用ESlint插件即可,它可以检查你的代码错误(如何使用ESlint在之前的框架中分享过,这里不再说明),如果不使用ESlint的话使用webpack进行相关的配置也可以检查代码的错误。

配置:

// 62.实现代码约束主要是通过两个loader解析来显示问题的
module.exports = {


  devServer: {
    client: {
       // 如果存在代码的书写错误,页面加载的时候会报错会显示在页面上,
       // 这里值为false的时候就不会显示了
      overlay: false,
    },
  },

  module: {
    rules: [
      {
        test: /\.js$/,
        // 常规安装webpack的插件
        //(webpack webpack-cli webpack-dev-server)之后还
        // 需要安装以下插件才行
        
        // npm i @babel/core babel-loader eslint-loader -D
        use: ['babel-loader', 'eslint-loader'],
      },
    ],
  },
};

webpack模块的解析

解析条件:

// 63


// 绝对路径:以当前的文件为中心,如果取本本文件夹中的文件的话'./'表示当前文件夹,
//          '../表示上一层文件夹等等操作来导入'


// 举例:引入自己写的文件math.js
const math = require('./math.js')
// 63


// 相对路径:相对于本文件所处的根目录来引入,引入方法跟上面引入没有什么区别





// 举例:引入自己在根目录文件夹下的文件math.js
const math = require('/math.js')
// 63


// 模块路径:相对于node_modules文件夹里面的文件





// 举例:引入Lodash这个JS库



// 引入的时候不需要加上node_modules,它会自动的拼接,直接写需要引入的
// 库名就可以了
import _ from 'loadsh'

路径的改写:

// 64.当文件夹嵌套多层的时候,写相对路径和绝对路径写多次肯定会很麻烦,
// 这里可以使用webpack来帮助简写路径





const path = require('path')
module.exports = {
    mode: 'development',
    entry: './src/app.js',
    resolve: {
         // 用来给路径起其他的名字的配置项
        alias: {
             // 如果想访问某个资源,并且 在前面加上@的符号的话,
             // 那么就会从src这个文件夹的下面开始查找
            '@': Path.resolve(__dirname,'./src')
        },



         // 解析查找文件类型的优先级,优先级从左到右依次降低
        extensions: [
            '.json','.js'
        ],
    }
}

cdn的加速(外部扩展)

// 65.一般用于首屏加载时间过长的优化方法之一(使用cdn进行加速)
module.exports = {


     // 与下面的配置是并列的,表示以那种标签的形式放在页面之上
    externalsType: script,
    
    // 用来定义外部的第三方的包,避免直接引入或者下载的话导致文件过大的问题
    externals: {
        // key的名字必须和引入包的名字需要是一样的,
        // 值为在window上暴露的哪一个对象
        jquery: [
            '使用的库的cdn的地址',
             // 引入的库的名字
            'jQuery'
        ]
    }, 
}

postCSS与CSS模块

postCSS: 用JS工具和插件来转换css代码,它会自动获取浏览器的流行度和能够支持的属性,根据这些属性自动为css规则添加前缀,将css的语法转换成浏览器能够理解的语法

CSS模块: 能够解决因为文件名的问题而产生的冲突

常规配置:

// 66.webpack.config.js






module.exports = {


    module: {

        // 前面说到过postCSS是用来处理CSS的文件的,自然需要在解析CSS的
        // 规则中进行使用,这些插件都需要安装,执行的顺序是从右往左的
        rules: [
            {
                test: /\.css$/,
                use: ['style-loader','css-loader','postcss-loader'], 
            }
        ],
    },
}
// 66.postcss.config.js






// 用于配置css的各种插件(重要的在于这个文件)
module.exports = {

    // 下面的这两个插件是需要安装的
    Plugins: [
        // 加载一些样式的前缀的插件
        require('autoprefixer'), 
        
        // 帮助浏览器去识别一个嵌套的样式
        require('postcss-nested') 
    ],
}
// 66.package.json






// 假设书写的css代码与浏览器的版本相关的话,需要在package.json中配置
// browserslist来实现版本的约束
"browserslist": [
    "> 1%",
    "last 2 versions"
  ]

TypeScript的集成

// 67.在使用TypeScript的时候,需要先安装TypeScript(使用)、ts-loader(解析)
//    两个插件
module.exports = {


    module: {

        rules: [
            {
                test: /\.ts$/,
                use: 'ts-loader',
                
                // 将指定的文件排出在解析的范围里面
                exclude: /node_modules/ 
            }
        ],
    },



    resolve: {
        // 定义识别的文件
        extensions: ['.ts', '.js'] 
    },
}

多文件打包

// 68
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {


    // 多文件打包主要依赖HtmlWebpackPlugin插件以及入口的配置
    plugins: [
        new HtmlWebpackPlugin({
            
            // 打包时使用的模板
            template: './index.html',
            
            // 打包后的文件名(这里如果防止路径的话不存
            // 在文件夹的时候会自动创建),其默认值是
            // index.html
            filename: 'age/index.html',
            
            // 打包那些文件
            chunks: 'main',
            
            // 还可以设置打包后文件名的前缀,
            // 在设置之后每个文件名前会多一串
            // 前缀
            publicPath:'www.baidu.com/'
        }),

        new HtmlWebpackPlugin({
            template: './index2.html',
            filename: 'age2/index2.html',
            chunks: 'main2',
        })
    ],

    entry: {
        main: {
            import: ['./src/app.js'],
            
            // [name]表示名字会随着文件名的变化而变化
            filename: 'age/[name].js'
        },
        main2: {
            import: ['./src/app.js'],
            filename: 'age2/[name].js'
        }
    }, 
}

tree-shaking

作用: 打包后的文件会将无关紧要的代码去掉,保证每句代码都是有意义的。

// 69
// math.js
// 定义两个函数
export const add = (a, b) => a + b



export const sum = (a, b) => (a + b) * 2
// main.js
// 然后我在main.js中使用上面定义的函数





import { add } from './math.js'



// 在这里使用add函数,在常规打包配置中,不做任何处理的话,math.js
// 中的两个函数都会被打包进来,不管那些代码有没有被使用
console.log( add(1, 2) )
// webpack.config.js






module.export = {
    // 在设置完这个之后,如果在开发环境下,他只会引入被使用的代码
    //(sum函数是不会被打包的),如果是在生产环境下,它会直接算出
    // 计算的结果
    optimization: {
        usedExports: true
    }
} 

sideEffects

说明: 并不是所有的模块的导入都会进行tree-shaking,比如全局的样式表或者是全局的JS文件,这些文件会带来一定的影响(具有副作用),会影响整个程序的运行,webpack4默认不做tree-shaking的操作,但是webpack5默认进行了tree-shaking的操作,那么如何指定是否有无副作用呢。

配置:

// 70.在package.json文件中存在一个sideEffects的配置选项,它表示是否有
//    副作用的意思。





// package.json
{
    // 表示所有的文件有副作用(默认不需要tree-shaking)
    "sideEffects": true
    
    // 表示所有的文件没副作用(默认需要tree-shaking)
    "sideEffects": false
    
    // 表示指定的文件有副作用(这些文件默认需要tree-shaking)
    "sideEffects": ['*.css'] // 所有的css文件
    "sideEffects": ['main.js'] // 仅仅只有main.JS文件有副作用....
}

© 版权声明
THE END
喜欢就支持一下吧
点赞0

Warning: mysqli_query(): (HY000/3): Error writing file '/tmp/MYgNJCP8' (Errcode: 28 - No space left on device) in /www/wwwroot/583.cn/wp-includes/class-wpdb.php on line 2345
admin的头像-五八三
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

图形验证码
取消
昵称代码图片