webpack介绍,webpack中的常用术语chunk,五个核心模块,打包html,开发服务器devserver,打包css,打包sass及less,抽离css文件,css3兼容处理(编译成各个浏览器支持的—前缀–),压缩css, css去掉无用的代吗,webpack打包资源,背景图打包,eslint代码规范,js兼容处理,树摇tree-shaking,entry多入口实现分割,optimization配置实现分割,路径别名与导入后缀省略,Source Maps调试配置

源码地址:https://gitee.com/cyp926/webpack-project.git
“webpack”: “^5.46.0”,
“webpack-cli”: “^4.7.2”,

一、webpack

1.1 webpack是什么

webpack是一种前端资源构建工具,一个静态模块打包器.在webpack看来,前端的所有资源文件(js/json/css/image/less/sass…)都会作为模块处理。它将根据模块的依赖关系进行静态分析,打包生成对应的静态资源
配置文件: webpack.config.js

1.2 五个核心内容

  • entry:入口。webpack是基于模块的,使用webpack首先需要指定模块解析入口(entry),webpack从入口开始根据模块间依赖关系递归解析和处理所有资源文件。
  • output:输出。源代码经过webpack处理之后的最终产物。
  • loader:模块转换器。本质就是一个函数,在该函数中对接收到的内容进行转换,返回转换后的结果。因为 Webpack 只认识 JavaScript,所以 Loader 就成了翻译官,对其他类型的资源进行转译的预处理工作。
  • plugin:扩展插件。基于事件流框架 Tapable,插件可以扩展 Webpack 的功能,在 Webpack 运行的生命周期中会广播出许多事件,Plugin 可以监听这些事件,在合适的时机通过 Webpack 提供的 API 改变输出结果。
  • mode 模式。通过选择 development 或 production 之中的一个,来设置 mode 参数,你可以启用相应模式下的 webpack 内置的优化

1.3 下载webpack的插件

npm init -y
npm i -D webpack webpack-cli

1.4 基本使用

const path = require(\'path\')
module.exports = {
   // https://webpack.docschina.org/configuration/mode/
  // 打包模式  development |  production
  mode: \'development\',
  // 项目入口
  entry: \'./src/index.js\',
  // 项目出口
  output: {
        path: path.resolve(path.dirname(__dirname), \'dist\'),
        // js/打包的位置, [name]默认的名称为main ,-[hash:8] 拼接hash
        filename: \'js/[name]-[hash:8].js\'
  }
}

运行打包命令行

  • npx webpack
  • npx webpack –mode development (不写配置情况下)
  • npx webpack 需要打包的文件 -o 打包的文件位置与名称 –mode development (不写配置情况下)

快捷配置

我们可以直接在package.json中配置:”build”:”webpack”

1.5 打包html

  • 安装:html-webpack-plugin
1)引入
const HtmlWebpackPlugin = require(\'html-webpack-plugin\')

2)打包压缩html(打包多个,就实例化new多个)
plugins: [
    new HtmlWebpackPlugin({
        title: \'欢迎来到Webpack\',打包设置标题 (可选项)
        template:\'./src/index.html\', //打包的文件
        filename:\'demo.html\',     //打包后的名称 (可选项)
        chunks:[],               //指定html中使用的js文件 (可选项)
        minify:{                  //压缩 (可选项)
            // 移除空格
            collapseWhitespace:true,
            // 移除注释
            removeComments:true,
        }
    }),
]

3)模板中使用定义的title
<title><%= htmlWebpackPlugin.options.title %></title>

1.6 开发服务器 devServer

  • npm i -D webpack-dev-server@3 (注意这里我们用到的是3版本的)
  • 命令 npx webpack serve
 // 在webpack5 需要加上这个选项才会自动刷新页面
target:"web"

配置devServer

 devServer:{

        contentBase: path.resolve(__dirname, \'../dist\'),// 运行代码目录(可选)  
        port:3001, //端口号   
        compress:true,//自动更新 (可选)  
        open:true//自动打开浏览器 (可选)  
        watchOptions: { ignored: /node_modules/}, // 忽略文件 (可选) 
        host: \'localhost\', // 域名(可选) 默认就是localhost
        clientLogLevel: \'none\', // 不要显示启动服务器的日志信息
        overlay: false,  // 如果出错,不要全屏提示
        // 服务器代理 --> 解决开发环境跨域问题
        proxy: {
        // 一旦devServer服务器接受到 /api开头的请求,就会把请求转发到另一个服务器
        \'/api\': {
            target: \'http://localhost:3000\',
            // 发送请求时,请求路径重写: 将/api 去除
            pathRewrite: {
            \'^/api\': \'\'
            }
        }
        }
    }

package.json中的scripts中配置命令

“serve”: “webpack-dev-server –config ./config/webpack.config.js”

1.7 打包css,sass等样式

1.7.1 打包css

webpack默认只支持js的打包,不支持其它类型,为了让它支持样式的打包就需要加载一些loader

  • npm i -D css-loader style-loader
   /* 
        一个用    loader:css-loader
        一个以上  use:[]
        从右往左
    */
    module:{
        rules:[
        
            {
                test: /\.css$/,
                use: [\'style-loader\',\'css-loader\']
            }
        ]
    }

1.7.2 打包less或者sass

  • less npm i -D less-loader
 {
    test: /\.less$/,
    use: [
        \'style-loader\',
        \'css-loader\',
        \'less-loader\'
    ]
}
  • sass npm i -D node-sass sass-loader
 {
    test: /\.sass$/,
    use: [
        \'style-loader\',
        \'css-loader\',
        \'sass-loader\'
    ]
}

1.7.3 提取抽离css为单独文件

  • npm i -D mini-css-extract-plugin
const miniCssExtractPlugin = require(\'mini-css-extract-plugin\')
module:{
    rules:[
        {
            test: /\.css$/,
            use: [
                miniCssExtractPlugin.loader, //写在第一行
                \'css-loader\']
        },
         {
            test: /\.css$/,
            use: [
                miniCssExtractPlugin.loader, //写在第一行
                \'css-loader\',
                \'sass-loader\'
                ]
        },
    ]
},
plugins:[
  new miniCssExtractPlugin({filename:\'demo.css\'})
]

1.7.4css3兼容处理(变异成各个浏览器支持的—前缀–)

  • npm i -D postcss-loader postcss-preset-env
  1. package.json配置兼容浏览器
  "browserslist": [
    ">0.2%",
    "last 2 version",
    "not dead"
  ]
  1. 新建文件postcss.config.js
module.exports={
    plugins:[
     require(\'postcss-preset-env\')()   
    ]
}
  1. 引入loader
{
    test: /\.css$/,
    use: [
        miniCssExtractPlugin.loader,
        \'css-loader\',
        \'postcss-loader\'
    ]
},

1.7.5 压缩css

  • npm i -D optimize-css-assets-webpack-plugin
plugins:[
    new optimizeCssAssetsWebpackPlugin()
]

1.7.6 css去掉无用的代吗

  • npm i -D purgecss-webpack-plugin
new PurgecssWebpackPlugin({
    paths:glob.sync(pattern:`${PATH.src}/**/*`,options:{nodir:true})
})

1.8 webpack打包资源

  • npm i -D url-loader file-loader html-loader

1.8.1 背景图打包

module: {
  rules: [
        {
            test: /\.(png|jpeg|jpg|gif)$/,
            loader: \'url-loader\',
            options: {
                publicPath:\'./images/\',
                outputPath: \'imgs/\',
                name:\'[name][hash].[ext]\',//命名hash+名称
                limit:1024*8,//限制8k一下转base64
            }
        },
         // 也可以这么写图片处理
        {
        test: /\.(png|jpeg|jpg|gif)$/,
        use: [
            {
            loader: \'url-loader\',
            options: {
                // 图片小于8kb,就会被base64处理
                // 优点: 减少请求数量(减轻服务器压力)
                // 缺点:图片体积会更大(文件请求速度更慢)
                limit: 8 * 1024,
                name: \'static/imgs/[name].[ext]\',
                publicPath: \'/dist\'
            }
            }
        ]
        },
    ]
}

1.8.2 html图 html-loader

module: {
  rules: [
    {
        test: /\.(html)$/,
        loader: \'html-loader\',
    }
  ]
}

1.8.3 其他文件打包

像项目中字体资源是不需要进行打包处理的,可以直接的通过复制方式给打包到目标目录中

module: {
  rules: [
        {
            // exclude 排查资源
            exclude:/\.(js|json|html|css|less|scss|png|jpg)$/,
            loader:\'file-loader\',
            options:{
                outputPath: \'font/\', //打包位置
                publicPath:\'./font\', //寻找位置
                name:\'[name][hasg].[ext]\',//命名hash+名称
            }
        }
    ]
}
  • 也可以这样处理静态资源
    • npm i -D copy-webpack-plugin
    const CopyPlugin = require(\'copy-webpack-plugin\')
    plugins: [
        new CopyPlugin({
            patterns: [
                {
                    // 来源
                    from: path.resolve(__dirname, \'../src/iconfont/\'),
                    // 目标
                    to: path.resolve(__dirname, \'../dist/iconfont\')
                },
                 {
                    // 来源
                    from: path.resolve(__dirname, \'../src/iconfont/\'),
                    // 目标
                    to: path.resolve(__dirname, \'../dist/iconfont\')
                }
            ]
        })
    ]
    

1.9 eslint代码规范(airbnb)

  • npm i -D eslint-loader eslint eslint-config-airbnb-base eslint-plugin-import
  1. package.json
 "eslintConfig":{
      "extends":"airbnb-base"
  }
  1. webpack.config.js
{
    test: /\.js$/,
    //只检查自己写的代码,不检查第三方的
    exclude:/node_modules/,
    loader:\'eslint-loader\'
},

1.10 js兼容处理

webpack在不需要引入任何loader可以对于js进行打包处理,但是它不会对于js兼容性进行任务的处理,而我们编写的项目是需要在不同的浏览器中运行的,此时就需要对于js的兼容性在打包过程中进行对应的处理。使用babel来完成对应的js兼容处理

  • npm i -D babel-loader @babel/core @babel/preset-env core-js@3
module: {
  rules: [
    // js兼容处理
    {
      test: /\.js$/,
      // 排除
      exclude: /node_modules/,
      loader: \'babel-loader\',
      options: {
        presets: [
          [
            \'@babel/preset-env\',
            {
              // 按需加载  inital  enter uage
              useBuiltIns: \'usage\',
              // 指定core-js版本
              corejs: 3,
              // 兼容性做到哪个版本的浏览器
              targets: {
                chrome: \'80\',
                firefox: \'50\',
                ie: \'9\',
                safari: \'10\',
                edge: \'17\'
              }
            }
          ]
        ]
      }
    }
  ]
}

二、环境优化

开发环境

- 打包构建速度
- 优化代码调试

生产优化(树摇)

- 代码运行性能

HMR模块热替换

 devServer:{
    port:3001,
    compress:true,//自动更新
    open:true,//自动打开浏览器
    hot:true//HMR模块热替换
}

树摇去掉没用到的js代码

  • tree-shaking webpack自帶
  1. es6 导出
  2. 必须是 production

可以:在package.json文件中添加了 “sideEffects”: false 表示所有代码都没有副作用(所有代码都可以进行tree shaking)

问题:可能会把 css的@babel/polyfill (副作用)文件删除掉
解决:”sideEffects”:[“*.css”]

css去掉无用的代吗

  • npm i -D purgecss-webpack-plugin
new PurgecssWebpackPlugin({
    paths:glob.sync(pattern:`${PATH.src}/**/*`,options:{nodir:true})
})

代码分割

1、通过配置入口文件来进行分割包,这是最简单和最直接的方式,但是这种方式有一定缺点,可能造成重复引用的模块重复被打包;

2、使用splitChunksPlugin来进行公共模块的提取(被optimizition.splitchunk取代);

3、通过动态代码加载来分割代码,使用import()方法,调用import() 之处,被作为分离的模块起点,意思是被请求的模块和它引用的所有子模块,会分离到一个单独的 chunk 中;

entry多入口实现分割

entry: {
    main: \'./src/js/index.js\',
    print: \'./src/js/print.js\'
},
output: {
    filename: "js/[name]-[contentHash].js",
    path: path.resolve(__dirname, "dist")
}

optimization配置实现分割

  • 过大的js文件拆分成多个,实现并行加载,提高加载速度(把工具库jq,lodash和业务逻辑拆分开)

可以将node_modules中代码单独打包一个chunk最终输出
chunks: 表示显示块的范围,有三个可选值:initial(初始块 同步)、async(按需加载块)、all(全部块),默认为all;

optimization: {
    splitChunks: {
      chunks: \'all\'
    }
},

externals忽略不打入的包

例如项目中使用从 CDN 引入 jQuery,而不是把它打包进来使用

externals: {
  jquery: \'jQuery\'
}

image

路径别名与导入后缀省略

  // 解析模块的规则
  resolve: {
    // 配置解析模块路径别名:优点简写路径,缺点路径没有提示
    alias: {
      // 定义一个@变量,可在import引入时使用
      \'@\': path.resolve(__dirname, \'../src\')
      \'$css\': path.resolve(__dirname, \'../src/css\')
    },
    // 配置省略文件路径的后缀名称 import \'@/index\'
    // 如果省略,建议文件名称不要重名了
    extensions: [\'.js\', \'.json\', \'.vue\']
  }

Source Maps调试配置

作为开发,代码调试当然少不了,那么问题来了,经过打包后的文件,你是不容易找到出错的地方的,Source Map就是用来解决这个问题的。

devtool: \'source-map\'  // 会生成对于调试的完整的.map文件,但同时也会减慢打包速度

三、代码

相关代码

webpack.config.js

// 采用commonjs
const path = require(\'path\')
const htmlWebpackPlugin = require(\'html-webpack-plugin\')
const miniCssExtractPlugin = require(\'mini-css-extract-plugin\')
const optimizeCssAssetsWebpackPlugin = require(\'optimize-css-assets-webpack-plugin\')
module.exports = {
    mode: \'production\',                 //生产:development,开发:production
    /* 
    1、entry:
        1、单入口,字符串表示-----打包一个chunk,生成一个build
            entry:\'./src/index.js\',
        2、多入口,数组------打包成一个chunk,生成一个build
            entry:[\'./src/index.js\',\'./src/cc.js\'],
        3、对象的写法  -----有几个文件生成几个chunk,生成几个build
            entry:{
                one:\'./src/one.js\',
                two:\'./src/two.js\'
            }
    */
    entry: \'./src/index.js\',
    output: {
        filename: \'[name].js\',
        // **对象多入口写法entry: filename:\'[name].js\',
        path: path.resolve(__dirname, \'dist\'),
    },
    // loader  处理非js资源   如html,css,img
    module: {
        rules: [
            /* 
                一个用    loader:css-loader
                一个以上  use:[]
                从右往左
                 {
                    test: /\.css$/,
                    use: [
                        \'style-loader\',
                        \'css-loader\']
                },
            */

            {
                test: /\.css$/,
                use: [
                    miniCssExtractPlugin.loader,
                    \'css-loader\',
                    \'postcss-loader\'
                ]
            },
            {
                test: /\.less$/,
                use: [
                    \'style-loader\',
                    \'css-loader\',
                    \'less-loader\'
                ]
            },
            {
                test: /\.sass$/,
                use: [
                    \'style-loader\',
                    \'css-loader\',
                    \'sass-loader\'
                ]
            },
            {
                test: /\.(png|jpg|jpeg)$/,
                loader: \'url-loader\',
                options: {
                    publicPath:\'./images/\',
                    outputPath: \'imgs/\',
                    name:\'[name][hasg].[ext]\',//命名hash+名称
                    limit:1024*8,//限制8k一下转base64
                }
            },
            {
                test: /\.(html)$/,
                loader: \'html-loader\',
            },
            {
                // exclude 排查资源
                exclude:/\.(js|json|html|css|less|scss|png|jpg)$/,
                loader:\'file-loader\',
                options:{
                    outputPath: \'font/\', //大包位置
                    publicPath:\'./font\', //寻找位置
                    name:\'[name][hasg].[ext]\',//命名hash+名称
                   
                }
            },
            // eslint 只检查js
            {
                test: /\.js$/,
               //只检查自己写的代码,不检查第三方的
               exclude:/node_modules/,
               loader:\'eslint-loader\',
               options:{
                   fix:true,//自动修复
               }
            },
        ]
    },
    // plugin插件,执行范围更广的任务  打包到开发压缩
    plugins: [
        // 打包压缩html(打包多个就实例化new多个)
        new htmlWebpackPlugin({
            template: \'./src/index.html\', //打包的文件
            filename: \'demo.html\',     //打包后的名称
            chunks: [],               //指定使用的js文件
            minify: {                  //压缩
                // 移除空格
                collapseWhitespace: true,
                // 移除注释
                removeComments: true,
            }
        }),
        new miniCssExtractPlugin({ filename: \'demo.css\' }),
        new optimizeCssAssetsWebpackPlugin()
    ],
    // 在webpack5 需要加上这个选项才会自动刷新页面
    target:"web",

    devServer:{
        port:3001,
        compress:true,//自动更新
        open:true,//自动打开浏览器
        hot:true//HMR模块热替换
    }
}

postcss.config.js

module.exports={
    plugins:[
     require(\'postcss-preset-env\')()   
    ]
}

相关依赖文件

package.json

{
  "name": "webpack5s",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev":"webpack serve --mode development --port 3000",
    "build":"webpack --mode production"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "css-loader": "^6.2.0",
    "eslint": "^7.31.0",
    "eslint-config-airbnb-base": "^14.2.1",
    "eslint-loader": "^4.0.2",
    "eslint-plugin-import": "^2.23.4",
    "file-loader": "^6.2.0",
    "html-loader": "^2.1.2",
    "html-webpack-plugin": "^5.3.2",
    "less": "^4.1.1",
    "less-loader": "^10.0.1",
    "mini-css-extract-plugin": "^2.1.0",
    "optimize-css-assets-webpack-plugin": "^6.0.1",
    "post-loader": "^2.0.0",
    "postcss-loader": "^6.1.1",
    "postcss-preset-env": "^6.7.0",
    "style-loader": "^3.2.1",
    "url-loader": "^4.1.1",
    "webpack": "^5.46.0",
    "webpack-cli": "^4.7.2",
    "webpack-dev-server": "^3.11.2"
  },
  "browserslist": [
    ">0.2%",
    "last 2 version",
    "not dead"
  ],
  "eslintConfig": {
    "extends": "airbnb-base"
  }
}

版权声明:本文为ypSharing原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/ypSharing/p/webpackHandler.html