webpack5的基本使用

209 阅读10分钟

一. 概念:一个资源构建工具(打包器),对浏览器不能识别的资源(less、sass、使用import、require引进的模块js、css等文件)进行压缩打包,转化成浏览器可以识别的代码。

二. webpack默认:

打包入口文件(entry): 根目录下的src/index.js

打包出口文件(output): 根目录下的dist/main.js

打包的模式(mode): production

根目录weback.config.js 文件中:

// resolve用来拼接绝对路径的方法+解构赋值
const {resolve}=require('path')
module.exports = {
    entry: "./src/index.js",
    output: {  
        filename: "main.js",
        path:resolve( __dirname + "dist"),
    },
    mode: "production", 
};

三. 实践:

1. 安装:

  • 初始化 在桌面新建一个文件夹webpackDemo,用vscode打开,在终端执行命令行 npm init -y ,在根目录生成 package.json 文件(不难发现,任何一个项目都有这个文件).
  • 全局安装:

全局安装稳定版本 npm install webpack webpack-cli -g

全局安装指定版本 npm install webpack@4.43.0 webpack-cli@3.3.12 -g

  • 本地安装: npm i webpack webpack-cli -D

2. 打包命令: npx webpack

3.更改webpack默认配置

  • 在根目录创建 webpack.config.js 文件夹:
const path =require('path') //引入node的path模块来拼接路径
module.exports = {
    entry:'./src/index.js',//打包入口文件
    output:{  //打包出口文件
        path:path.resolve(__dirname,'build'),  //出口文件目录地址(绝对路径),__dirname定位到了根目录,拼接上 build 
        filename:'index.js',//出口文件名
    },
    mode:'production',//打包的模式development(代码未压缩)、 production(代码压缩了,并删除没必要的代码)两种
}

4.loaders的配置

以上三步就可以对js模块打包处理了。由于webpack默认只能对js文件打包处理,那么对于其他资源的打包就得在loaders转换器中引入其他工具,loaders的配置都在module对象的rules中配置。

(1)对css打包: 根目录下载 npm i style-loader css-loader -D

module:{
        rules:[
            // 打包css
            {
                test: /\.css$/i, //正则匹配需要打包的文件名
                use:['style-loader','css-loader'],//打包需要的loader,注意顺序
            }
        ]
    }

(1-1)使用style-loader会将打包的css(less/sass)文件装载到打包的js文件里,想webpack打包时生成单独的css文件(CSS 文件分离),安装插件: npm i mini-css-extract-plugin -D ,然后再webpack.config.js中配置:

  • 引入插件:
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
  • 修改css的loader,将style-loader改成插件的loader
            // 打包css
            {
                test: /\.css$/i, //正则匹配需要打包的文件名
                use:[MiniCssExtractPlugin-loader,'css-loader'],//打包需要的loader,注意顺序
            }
  • 还要在plugins配置项中引用插件
 plugins:[
        // 使用html插件
        new HtmlWebpackPlugin({
            //复制 ./src/index.html 文件,并且自动引入打包输出的所有资源(js/css)
            template:'./index.html',
            title:'这个是打包后的标题',
        }),
        // 使用单独生成css文件的插件,打包时会将css文件独立出去
        new MiniCssExtractPlugin({
            // 指定文件的输出路径和文件名
            filename: 'css/index.css'
        })
    ],

打包后效果图:

1.png

(1-2)postcss-loader处理css兼容: 根目录下载 npm i postcss-loader autoprefixer -D

  • 在打包css的loader处配置:
          // 打包css
         {
                test: /\.css$/i, //正则匹配需要打包的文件名
                use:[MiniCssExtractPlugin.loader,'css-loader',
                        //添加postcss-loader
                        {
                            loader:'postcss-loader',
                            //配置参数
                            options:{
                            postcssOptions:{
                                //添加插件autoprefixer,只是添加前缀
                                plugins:[
                                    require('autoprefixer')
                                ]
                            }
                            }
                        }
            ],//打包需要的loader,注意顺序
                exclude:/node-moules/,//不需要查找解析的文件

         },
  • 在index.js同级下新建一个名为.browserslistrc 文件写兼容的条件,比如:

1.png

打包后效果图:

1.png

兼容条件分别表示: 更多 .browserslistrc 配置

"last 1 chrome version" 表示兼容最近版本的 chrome

"last 1 firefox version", "last 1 safari version"

">0.1%" 表示大于 99.9% 的浏览器

"not dead" 表示不要已经死去的浏览器(如 IE10)

"not op_mini all" 表示要 欧朋mini 浏览器 (不兼容已经死去的浏览器)

(1-3)如果还需要更强的兼容需要下载 npm i postcss-preset-env -D

  • 在webpack.config.js配置:
  // 打包css
  {
         test: /\.css$/i, //正则匹配需要打包的文件名
         use:[MiniCssExtractPlugin.loader,'css-loader',
                  //添加postcss-loader
                 {
                     loader:'postcss-loader',
                     //配置参数
                     options:{
                        postcssOptions:{
                            //添加插件autoprefixer,能加前缀
                            plugins:['postcss-preset-env']
                        }
                     }
                 }

            ],//打包需要的loader,注意顺序
         exclude:/node-moules/,//不需要查找解析的文件

  },
  • 同时在package.json中配置browserlist: 插件postcss-preset-env是给postcss找到package.json中的browserlist里面的配置,通过配置加载指定的css兼容性样式。(此时之前创建的 .browserslistrc 文件可以删除了)
"browserslist":{
     
         "development": [
             "last 1 chrome version",  
             "last 1 firefox version",
             "last 1 safari version"
         ],
         "production":[
             ">0.2%", 
             "not dead", 
             "not op_mini all" 
         ]
     }

(1-3-1)另外一种写法:通常在index.js 同级下新建一个名为 postcss.config.js 文件:

1.png

  • 写配置如下:
module.exports = {
    plugins: [
        require('postcss-preset-env')
    ]
}
  • 在webpack.config.js配置文件里直接导入 postcss-loader 就行:
 // 打包css
 {
     test: /\.css$/i, //正则匹配需要打包的文件名
     use:[MiniCssExtractPlugin.loader,'css-loader','postcss-loader',],
     exclude:/node-moules/,//不需要查找解析的文件

 },

(2)对less打包:根目录下载 npm i less less-loader -D

module:{
        rules:[
            // 打包css
            {
                test: /\.css$/i, //正则匹配需要打包的文件名
                use:['style-loader','css-loader'],//打包需要的loader,注意顺序
                exclude:/node-moules/,//不需要查找解析的文件,提高webpack解析效率
            },
            //打包less
            {
                test:/\.less$/i,
                use:['style-loader','css-loader','less-loader'],
                exclude:/node-moules/
            },
        ]
    }

(3)对sass打包:根目录下载 npm i sass-loader node-sass -D

module:{
        rules:[
            // 打包css
            {
                test: /\.css$/i, //正则匹配需要打包的文件名
                use:['style-loader','css-loader'],//打包需要的loader,注意顺序,数组项越靠后越先执行(从下到上,从右到左)
                exclude:/node-moules/,//不需要查找解析的文件
            },
            //打包less
            {
                test:/\.less$/i,
                use:['style-loader','css-loader','less-loader'],
                exclude:/node-moules/,//不需要查找解析的文件
            },
            //打包scss
            {
                test:/\.scss$/i,
                use:['style-loader','css-loader','sass-loader'],
                exclude:/node-moules/,
            },
        ]
    }

(4)对图片的打包

  • 4.1 使用asset对url的图片打包 如background: url() , 使用第一种方法可以不用下载任何loader
const path =require('path') //引入node的path模块来拼接路径
//第一步下载插件,第二步 引入html插件
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
    entry:'./src/index.js',//打包入口文件
    output:{  //打包出口文件
        path:path.resolve(__dirname,'build'),  //出口文件目录地址(绝对路径),__dirname定位到了根目录,拼接上 build 
        filename:'index.js',//出口文件名
    },
    mode:'production',
    module:{//loaders的配置都在module对象的rules中配置
        rules:[
            // 打包css
            {
                test: /\.css$/i, //正则匹配需要打包的文件名
                use:['style-loader','css-loader'],//打包需要的loader,注意顺序
                exclude:/node-moules/,//不需要查找解析的文件
            },
            //打包less
            {
                test:/\.less$/i,
                use:['style-loader','css-loader','less-loader'],
                exclude:/node-moules/,//不需要查找解析的文件
            },
            //打包scss
            {
                test:/\.scss$/i,
                use:['style-loader','css-loader','sass-loader'],
                exclude:/node-moules/,//不需要查找解析的文件
            },
            // 打包图片(第一种方法使用asset)
            {
                //正则表达式,表示图片文件
                test:/\.(png|jpg|gif|svg)$/i,
                type: 'asset',
                generator: {
                    // 打包后会放到images文件夹下  hash缓存
                    filename: 'images/[contenthash][ext][query]', 
                }
            },
        ]
    },
    
}

注意:图片文件放在src目录下的images文件夹下,最主要是 background: url(./src/images/1.jpg)no-repeat center top; 一定不能放在html文件中的style里面:

1.png

打包图片另一种方法

根目录下载 npm i file-loader url-loader -D , 在webpack5中url-loader、file-loader已经弃用,若要使用,添加type: 'javascript/auto'; 注意要在打包出口文件(output)中配置打包后的地址: assetModuleFilename: 'images/[hash][ext][query]'

            // 打包图片
            {
                test:/\.(png|jpg|gif|svg)$/i,
                dependency: { not: ['url'] }, //添加该属性让资源输出到output指定文件夹中
                loader:'file-loader',//url-loader 一样
                options:{
                    limit:8*1024,//如果图片小于8k,就使用base64处理
              //url-loader默认采用ES6模块语法,关闭es模块语法(html中的img图片资源打包时使用commonjs)
                    esModule: false,
                    //打包后名字的长度,ext表示原来的文件类型(png,jpg)
                    name:'[hash:5].[ext]'
                },
                type: 'javascript/auto',
            
            },

若报错:使用url-loader处理图片时,设置了 limit:81024, 那么只能处理小于这个值的图片,大于这个值的图片就无法处理了,所以代码会报错,此时可以结合file-loader来处理超出10000的图片,这样代码就不会报错了。 如果不设置limit:81024; 那么无论图片多大,都会转成base64格式的

(4.2)对html中的img标签图片打包: 根目录下载 npm i html-withimg-loader -D

// 打包html中的img标签图片
   {
     test:/\.html$/i,
     loader:'html-withimg-loader'
   }

(5)对html打包:目前在打包后的文件目录下还没有html页面,通过 html-webpack-plugin 插件完成html打包,根目录下载插件:  npm i html-webpack-plugin -D ,所有插件配置在plugins数组里面。

const path =require('path') //引入node的path模块来拼接路径
//第一步下载插件,第二步 引入html插件
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
    entry:'./src/index.js',//打包入口文件
    output:{  //打包出口文件
        path:path.resolve(__dirname,'build'),  //出口文件目录地址(绝对路径),__dirname定位到了根目录,拼接上 build 
        filename:'index.js',//出口文件名
    },
    mode:'production',
    module:{//loaders的配置都在module对象的rules中配置
        rules:[
            // 打包css
            {
                test: /\.css$/i, //正则匹配需要打包的文件名
                use:['style-loader','css-loader'],//打包需要的loader,注意顺序
                exclude:/node-moules/,//不需要查找解析的文件
            },
            //打包less
            {
                test:/\.less$/i,
                use:['style-loader','css-loader','less-loader'],
                exclude:/node-moules/,//不需要查找解析的文件
            },
            //打包scss
            {
                test:/\.scss$/i,
                use:['style-loader','css-loader','sass-loader'],
                exclude:/node-moules/,//不需要查找解析的文件
            },
        ]
    },
    plugins:[//作用:默认在打包出口文件生成一个空的html文件,自动引入打包输出的所有资源(js/css)
        //如果需要一个有结构的html文件,那么添加参数比如: {template:'./src/index.html'}
        //第三步 使用html插件
        new HtmlWebpackPlugin({
            template:'./index.html' ,//这个是我的html文件路径,大家的不一定相同
        })
    ],

}

(6)使用asset打包字体图标

            //使用asset 打包字体图标
            {
                test: /.(woff|woff2|eot|ttf|otf)$/i,
                type:'asset/resource',
                generator:{
                    filename:'font/[name].[hash:3][ext]'
                },
            }

(7) webpack-dev-server 插件的使用:用于搭建一个webpack的服务器,模拟一个线上环境 ,手动运行 npx webpack  会显得很麻烦,它帮助我们在代码发生变化后自动打开浏览器和自动刷新页面的功能:

devServer: {
        static: { // 项目构建后路径 不在支持 contentBase
            directory: path.resolve(__dirname, "build"),
          },
          // 启动gzip压缩 优点:对JS,CSS资源的压缩率很高,可以极大得提高文件传输的速率,从而提升web性能
            //缺点:服务端要对文件进行压缩,而客户端要进行解压,增加了两边的负载
        compress: true,
        //lazy:true,//懒编译,使用多入口时很有用,只有在我们访问那个入口时才进行编译,就不必将所有的入口一次性全部编译,提高我们编译的速度
        open: true, //打开浏览器
        host: "localhost", //本地域名
        port: 8081, //端口号
        hot: true, //热加载,开启HMR功能(只能用于开发环境,生产环境不需要了)
        //使用 History 路由模式,这个配置属性是用来应对返回404页面时定向到特定页面用的
        historyApiFallback: true,
        // 代理配置
        proxy: {
            '/proxyAPI': {
                target: `https://zhelihongyi.haiyan.gov.cn:10002`, // 需要代理的后台接口地址,通常是开发时的测试地址
                // ws: true, // 代理 websockets
                secure: false, // 如果是https接口,需要配置这段代码;不是,则不写
                changeOrigin: true, // 是否跨域
                pathRewrite: { //把代理重写为空,因为别人没有 /api
                    '/proxyAPI': '',
                },
            },
            
        },
        
    },
  • package.json中的scripts下添加配置:
"scripts": {
    "test": "echo "Error: no test specified" && exit 1",
    "dev":"webpack-dev-server --open"

  },

运行命令:npm run dev 注意使用这个命令打开的资源开发环境的index.html,更新开发数据后是无法自动打包资源的(只能执行npx webpack)

(8)webpack-dev-server的HMR模块 热替换机制

一个模块发生变化,只会重新打包这一个模块(而不是打包所有模块),极大的提升构建速度。在webpack.config.js文件中添加:

devServer: {
        open: true, //打开浏览器
        host: "localhost", //本地域名
        port: 8081, //端口号
        hot: true, //热加载,开启HMR功能(只能用于开发环境,生产环境不需要了)
    },

(9) babel在webpack中的使用

概念:是一个 JavaScript 编译器,用于将 ECMAScript 2015+ 版本的代码转换为向后兼容的 JavaScript 语法,以便能够运行在当前和旧版本的浏览器或其他环境中.

安装:

  • babel-loader(Webpack中用于处理js文件的Loader,可以使用babel的功能)
  • @babel/core(babel核心功能库)
  • @babel/preset-env(一个智能预设:插件集合,转换你所使用的最新JavaScript)

babel在webpack中的使用参考:blog.csdn.net/weixin_4745…

扩展:babel的使用方法参考:

最后附上 webpack.config.js 文件完整代码:

const path =require('path') //引入node的path模块来拼接路径
//第一步下载插件,第二步 引入html插件
const HtmlWebpackPlugin = require('html-webpack-plugin')
// 引入将css生成单独文件的插件
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
module.exports = {
    entry:'./src/index.js',//打包入口文件
    output:{  //打包出口文件
        path:path.resolve(__dirname,'build'),  //出口文件目录地址(绝对路径),__dirname定位到了根目录,拼接上 build 
        filename:'index.js',//出口文件名
        // assetModuleFilename: 'images/[hash][ext][query]',
    },
    mode:'production',
    module:{//loaders的配置都在module对象的rules中配置
        rules:[
            // 打包css
            {
                test: /\.css$/i, //正则匹配需要打包的文件名
                use:[MiniCssExtractPlugin.loader,'css-loader','postcss-loader',],//打包需要的loader,注意顺序
                exclude:/node-moules/,//不需要查找解析的文件
            },
            //打包less
            {
                test:/\.less$/i,
                use:[MiniCssExtractPlugin.loader,'css-loader','less-loader'],
                exclude:/node-moules/,//不需要查找解析的文件
            },
            //打包scss
            {
                test:/\.scss$/i,
                use:[MiniCssExtractPlugin.loader,'css-loader','sass-loader'],
                exclude:/node-moules/,//不需要查找解析的文件
            },
            // 打包图片(第一种方法:使用asset)
            {
                //正则表达式,表示图片文件
                test:/\.(png|jpg|gif|svg)$/i,
                type: 'asset',
                generator: {
                    // 打包后会放到images文件夹下  hash缓存
                    filename: 'images/[contenthash][ext][query]', 
                }
            },
            // 打包html中的img标签图片
            {
                test:/\.html$/i,
                loader:'html-withimg-loader',
            },
            //使用asset 打包字体图标
            {
                test: /\.(ttf|woff|woff2?)$/i,
                type:'asset/resource',
                generator:{
                    filename:'font/[name].[hash:3][ext]'
                },
            }
        ]
    },
    plugins:[//作用:默认在打包出口文件生成一个空的html文件,自动引入打包输出的所有资源(js/css)
        //如果需要一个有结构的html文件,那么添加参数 {template:'./src/index.html'}
        //第三步 使用html插件
        new HtmlWebpackPlugin({
            //复制 ./src/index.html 文件,并且自动引入打包输出的所有资源(js/css)
            template:'index.html',
            title:'这个是打包后的标题',
        }),
        // 使用单独生成css文件的插件,打包时会将css文件独立出去
        new MiniCssExtractPlugin({
            // 指定文件的输出路径和文件名
            filename: 'css/index.css'
        })
    ],
    devtool: 'nosources-source-map',//生产模式一般不开启sourcemap
    devServer: {
        static: { // 项目构建后路径 不在支持 contentBase
            directory: path.resolve(__dirname, "build"),
          },
          // 启动gzip压缩 优点:对JS,CSS资源的压缩率很高,可以极大得提高文件传输的速率,从而提升web性能
            //缺点:服务端要对文件进行压缩,而客户端要进行解压,增加了两边的负载
        compress: true,
        // lazy:true,//懒编译,使用多入口时很有用,只有在我们访问那个入口时才进行编译,就不必将所有的入口一次性全部编译,提高我们编译的速度
        open: true, //打开浏览器
        https:true,
        host: "localhost", //本地域名
        port: 8081, //端口号
        hot: true, //热加载,开启HMR功能(只能用于开发环境,生产环境不需要了)
        //使用 History 路由模式,这个配置属性将会在响应404时返回index.html
        historyApiFallback: true,
        // 代理配置
        proxy: {
            '/proxyAPI': {
                target: `https://zhelihongyi.haiyan.gov.cn:10002`, // 需要代理的后台接口地址,通常是开发时的测试地址
                // ws: true, // 代理 websockets
                secure: false, // 如果是https接口,需要配置这段代码;不是,则不写
                changeOrigin: true, // 是否跨域
                pathRewrite: { //把代理重写为空,因为别人没有 /api
                    '/proxyAPI': '',
                },
            },
            
        },
        
    },

}

附上package.json文件:

{
  "name": "webpack-demo",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "webpack-dev-server --open"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "autoprefixer": "^10.4.14",
    "css-loader": "^6.7.3",
    "file-loader": "^6.2.0",
    "html-webpack-plugin": "^5.5.0",
    "html-withimg-loader": "^0.1.16",
    "less": "^4.1.3",
    "less-loader": "^11.1.0",
    "mini-css-extract-plugin": "^2.7.5",
    "node-sass": "^8.0.0",
    "postcss-loader": "^7.1.0",
    "postcss-preset-env": "^8.0.1",
    "sass-loader": "^13.2.1",
    "style-loader": "^3.3.2",
    "url-loader": "^4.1.1",
    "webpack": "^5.76.3",
    "webpack-cli": "^5.0.1",
    "webpack-dev-server": "^4.13.1"
  },
  "browserslist": {
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ],
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ]
  },
  "dependencies": {
    "@babel/polyfill": "^7.12.1"
  }
}

总结: 五个核心概念

  • Entry 表示打包的入口文件
  • Output 出口文件 , 打包后的文件资源在哪,叫什么名字
  • Loader 处理less,sass,img文件(相当于翻译官)
  • Plugins 插件,处理更强大的事情,打包优化压缩
  • Mode development开发模式,production生产模式

demo地址