轻松搞定webpack5.x

源码地址: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"
  }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值