乐趣区

关于webpack:2022webpack5实战教程

前言

手摸手教你如何打包,让你在入手的实际过程中感触 webpack。
在入手之前,你可先简略理解一下 webpack 的概念
每一小结都有对应的分支,不便大家学习
webpack 版本:5.58.1

入门

新建一个目录,初始化 npm
npm init
接下来装置 webpackwebpack-cli两个包
npm i -D webpack webpack-cli

默认配置

新建一个文件夹 src , 外面新建一个main.js, 写一点测试代码
console.log("webpack")
在 package.json 中 scripts 中增加新的命令

"scripts": {"build": "webpack ./src/main.js"},

执行打包命令 npm run build
此时如果生成了一个 dist 文件夹,并且外部含有 main.js 阐明曾经打包胜利了
这个例子只是 webpack 本人默认的配置,上面咱们要实现更加丰盛的自定义配置

自定义配置

新建一个 build 文件夹, 外面新建一个webpack.config.js

const path = require('path');

module.exports = {
  mode:'development', // 开发模式
  entry: path.resolve(__dirname,'../src/main.js'), // 入口文件
  output: {
      filename: 'output.js', // 打包后的文件名称
      path: path.resolve(__dirname,'../dist') // 打包后的目录
  }
}

更改打包命令

{
  // ...
  "scripts": {"build": "webpack --config build/webpack.config.js"},
}

而后执行 npm run build,会失去如下后果

其中 main.js 是咱们第一次打包遗留的。
js 曾经打包好了,接下来咱们要做的就是将 js 引入到 html 文件中

增加 js 到 html 文件

咱们须要 html-webpack-plugin 来帮咱们实现这件事件
npm i -D html-webpack-plugin
新建一个与 build 同级的文件夹 public, 外面新建一个index.html
配置如下

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
  mode:'development', // 开发模式
  entry: path.resolve(__dirname,'../src/main.js'), // 入口文件
  output: {filename: '[name].[hash:8].js', // [name] 指 entry 属性名字, 默认为 main
      path: path.resolve(__dirname,'../dist') // 打包后的目录
  },
  plugins:[
    new HtmlWebpackPlugin({
      // 选取一个 html 作为模版,在 dist 目录下会生成一个雷同的 html,之后将打包好的 js 注入到该 html 文件
      template: path.resolve(__dirname,'../public/index.html') 
    })
  ]
}

打包胜利之后,查看 dist 目录下的 index.html 文件是否援用了打包之后的 js

多文件如何注入到 html

  1. 多个入口文件,注入到同一个 html 文件中

这种情景咱们只需增加入口就 OK 了,html-webpack-plugin插件会主动把所有打包好的 js 注入到 html 里

module.exports = {
  // ...
  entry: {main: path.resolve(__dirname,'../src/main.js'),
    share: path.resolve(__dirname,'../src/share.js')
  }
}
  1. 多个入口文件,依据不同需要注入到不同的 html 文件

咱们能够通过生成多个 html-webpack-plugin 实例来解决这个问题

module.exports = {
 // ...
  plugins:[
    new HtmlWebpackPlugin({
      // 选取一个 html 作为模版,在 dist 目录下会生成一个雷同的 html,之后将打包好的 js 注入到该 html 文件
      template: path.resolve(__dirname,'../public/index.html'),
      filename: 'index.html',
      chunks: ['main'] // 配置将哪些文件注入到该 html 文件,为 [] 在代表不注入 js,若无该属性,默认注入所有 js}),
    new HtmlWebpackPlugin({template: path.resolve(__dirname,'../public/share.html'),
      filename: 'share.html',
      chunks: ['share']
    })
  ] 
}

打包前清空 dist 目录

置信大家也发现了,dist 目录下的文件越来越多,上面咱们就来解决这个问题
咱们须要 clean-webpack-plugin 来帮咱们实现这件事件
npm i -D clean-webpack-plugin

// 其余配置同上
const {CleanWebpackPlugin} = require('clean-webpack-plugin')

module.exports = {
   plugins:[
    // ...
    new CleanWebpackPlugin()] 
}

经掘友揭示,webpack5 有新增清空 dist 目录的形式,在 output 减少 clean 字段,现补充在上面

module.exports = {
  // ...
  output: {filename: '[name].[hash:8].js', // [name] 指 entry 属性名字, 默认为 main
      path: path.resolve(__dirname,'../dist'), // 打包后的目录
      clean: true
  },
}

将 css 以 style 标签的形式注入到 html

咱们的入口文件是 js,所以咱们在入口 js 中引入咱们的 css 文件

// main.js
import "../static/css/base.css"
import "../static/css/color.scss"
import "../static/css/fontsize.less"

console.log("webpack")

咱们须要一些 loader 来解析咱们的 css 文件
npm i -D style-loader css-loader
如果应用 less 来构建款式,则须要装置
npm i -D less less-loader
如果应用 scss 来构建款式,则须要装置
npm i -D node-sass sass-loader
配置文件如下

module.exports = {
  // ...
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ["style-loader", "css-loader"] // 从右向左开始解析
      },
      {
        test: /\.scss$/,
        use: ["style-loader", "css-loader", "sass-loader"] // 此外还须要装置 node-sass(sass 也行)
      },
      {
        test:/\.less$/,
        use:['style-loader','css-loader','less-loader'] // 此外还须要装置 less 模块
      }
    ]
  }
}

打包之后在浏览器中关上 html 文件,就能看见咱们注入的 css

为 css 增加浏览器前缀

为了适配更多的浏览器款式咱们须要给 css 加上前缀
咱们须要 postcss-loader 以及 autoprefixer 来帮咱们实现这件事件

参考 webpack 视频解说:进入学习

引入 autoprefixer 形式有两种

  1. postcss.config.js引入(举荐)

** 我的项目根目 ** 录下创立postcss.config.js, 配置如下

module.exports = {
  plugins: [require('autoprefixer')
  ]
}

而后间接在 webpack.config.js 中引入

module.exports = {
  // ...
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ["style-loader", "css-loader", "postcss-loader"] // 从右向左开始解析
      },
      {
        test: /\.scss$/,
        use: ["style-loader", "css-loader", "postcss-loader", "sass-loader"] // 此外还须要装置 node-sass(sass 也行)
      },
      {
        test:/\.less$/,
        use:['style-loader','css-loader', "postcss-loader", 'less-loader'] // 此外还须要装置 less 模块
      }
    ]
  } 
}
  1. 间接在 webpack.config.js 配置
moudule.exports = {
 // ...
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ["style-loader", "css-loader", {
          loader: "postcss-loader",
          options: {
            postcssOptions: {
              plugins: [['autoprefixer']
              ]
            }
          }
        }] // 从右向左开始解析
      },
      {
        test: /\.scss$/,
        use: ["style-loader", "css-loader", {
          loader: "postcss-loader",
          options: {
            postcssOptions: {
              plugins: [['autoprefixer']
              ]
            }
          }
        }, "sass-loader"] // 此外还须要装置 node-sass(sass 也行)
      },
      {
        test:/\.less$/,
        use:['style-loader','css-loader', {
          loader: "postcss-loader",
          options: {
            postcssOptions: {
              plugins: [['autoprefixer']
              ]
            }
          }
        }, 'less-loader'] // 此外还须要装置 less 模块
      }
    ]
  } 
}

实现上述配置之后,咱们发现 css 并未胜利加上前缀。这里咱们还要进行一步操作,那就是配置 package.json, 在package.json 中增加如下配置

{
 // ...
"browserslist": [
    "defaults",
    "not ie < 11",
    "last 2 versions",
    "> 1%",
    "iOS 7",
    "last 3 iOS versions"
  ]
}

外链引入 css 文件

上述咱们通过 style 标签的形式加载咱们的款式,但如果 css 文件过多就显得很凌乱。
咱们须要 mini-css-extract-plugin 帮咱们实现
npm i -D mini-css-extract-plugin

// 其余配置放弃不变
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  // ...
  plugins: [
    // ...
    new MiniCssExtractPlugin({filename: "[name].[hash].css",
    })
  ],
    module: {
    rules: [
      {
        test: /\.css$/,
        use: [MiniCssExtractPlugin.loader, "css-loader", "postcss-loader"] // 从右向左开始解析
      },
      {
        test: /\.scss$/,
        use: [MiniCssExtractPlugin.loader, "css-loader", {
          loader: "postcss-loader",
          options: {
            postcssOptions: {
              plugins: [['autoprefixer']
              ]
            }
          }
        }, "sass-loader"] // 此外还须要装置 node-sass(sass 也行)
      },
      {
        test:/\.less$/,
        use:[MiniCssExtractPlugin.loader,'css-loader', "postcss-loader", 'less-loader'] // 此外还须要装置 less 模块
      }
    ]
  }
}

不过通过这种形式会将所有的 css 合并到一个 css 文件里,如果想要拆分就只有用其余方法里,网上看他人用的是extract-text-webpack-plugin,不过当我去 npm 官网看时。

所以这里就先不探讨拆分 css 了

图片解决

css 与 js 中图片解决只需增加如下配置就行

module.exports = {
    // ...
  module: {
    rules: [
        // ...
      {test: /\.(jpe?g|png|gif)$/i,
        type: "asset",
        generator: {filename: 'static/[name].[hash].[ext]'
        }
      },
    ]
  }
}

如果须要解决 html 中的图片则须要用到 html-loader
npm i -D html-loader
配置如下

module.exports = {
    // ...
  module: {
    rules: [
        // ...
      {
        test: /\.html$/i,
        loader: "html-loader"
      },
    ]
  }
}

如果须要配置更多的资源文件,请参考资源模块

本义 js 文件

为了使咱们的 js 代码兼容更多的环境咱们须要本义咱们的 js 文件
npm i -D babel-loader @babel/preset-env @babel/core core-js

module.expors = {
  // ...
  module: {
    rules: [
      // ...
      {
        test: /\.js$/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: [
              [
                '@babel/preset-env',
                {
                  useBuiltIns: 'usage',
                  corejs: {
                    //core-js 的版本
                    version: 3
                  },
                  // 须要兼容的浏览器
                  targets: {
                    chrome: '60',
                    firefox: '60',
                    ie: '9',
                    safari: '10',
                    edge: '17'
                  }
                }
              ]
            ],
          }
        },
        exclude: /node_modules/
      }
    ]
  }
}

babel-loader负责将 ES6/7/ 8 等语法转换为 ES5 语法
core-js负责将新的 api 进行转化,例如 promise、Generator、Set、Maps、Proxy 等

进阶

搭建 Vue 开发环境

Vue 文件解决

首先装置必要依赖
npm i -D vue-loader vue-template-compiler vue-style-loader
npm i -S vue
vue-loader 用于解析 .vue 文件
vue-template-compiler 用于编译模板
vue-style-loader 解析款式

const vueLoaderPlugin = require('vue-loader/lib/plugin')
module.exports = {
  // ...
  module:{
    rules:[
      // 这一个 loader 必须放在最后面
      {
        test:/\.vue$/,
        use:['vue-loader']
      }
      // ...
    ]
  },
  resolve:{
    // 设置门路别名
    alias:{
      'vue$':'vue/dist/vue.runtime.esm.js',
      '@':path.resolve(__dirname,'../src')
    },
    // 尝试按程序解析这些后缀名。// 如果有多个文件有雷同的名字,但后缀名不同,webpack 会解析列在数组首位的后缀的文件 并跳过其余的后缀。extensions:['*','.js','.json','.vue']
  },
  plugins:[new vueLoaderPlugin()
  ]
}

热更新配置

咱们须要应用 webpack-dev-server 来启动一个本地服务并且配置热更新
npm i -D webpack-dev-server
配置如下

const Webpack = require('webpack')
module.exports = {
  // ...
  devServer:{
    port:3000,
    hot:true
  },
  plugins:[new Webpack.HotModuleReplacementPlugin()
  ]
}

配置打包命令

"scripts": {
  // ...
  "dev": "webpack-dev-server --config build/webpack.config.js --open"
},

增加 --open可主动关上 http://localhost:3000页面
接下来写几行代码进行测试,先批改咱们的 main.js

// main.js
import Vue from 'vue'
import App from './App.vue'

new Vue({render: h => h(App)
}).$mount('#app')

新建一个 App.vue 文件

<template>
  <div>
    {{msg}}
  </div>
</template>

<script>
export default {data() {return {      msg: "webpack vue"}  }}
</script>

<style lang='scss' scoped>
div {color: aquamarine;  display: flex;}
</style>

批改原来的 index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>webpack</title>
</head>
<body>
  <div id="app"></div>
</body>
</html>

最初执行npm run dev

辨别开发环境和生产环境

development(开发环境)production(生产环境) 这两个环境下的构建指标存在着微小差别。在开发环境中,咱们须要:弱小的 source map 和一个有着 live reloading(实时从新加载) 或 hot module replacement(热模块替换) 能力的 localhost server。而生产环境指标则转移至其余方面,关注点在于压缩 bundle、更轻量的 source map、资源优化等,通过这些优化形式改善加载工夫。因为要遵循逻辑拆散,咱们通常倡议为每个环境编写彼此独立的 webpack 配置。
咱们在原来 webpack.config.js 的根底上再新增两个文件 webpack.prod.jswebpack.dev.js
这里咱们须要应用 webpack-merge 帮咱们 merge 代码
npm i -D webpack-merge

// webpack.dev.js
const {merge} = require('webpack-merge');
const common = require('./webpack.config.js')

module.exports = merge(common, {
  mode: 'development',
  devtool: 'inline-source-map',
  devServer:{
    port:3000,
    hot:true
  }
});
// webpack.prod.js
const {merge} = require('webpack-merge');
const common = require('./webpack.config.js');

module.exports = merge(common, {mode: 'production',});

原先的 webpack.config.js 也须要做出批改,咱们只须要删除 modedevserver字段就行了
最初批改 package.json 中的 scripts 命令

"scripts": {
    "build": "webpack --config build/webpack.prod.js",
    "dev": "webpack-dev-server --config build/webpack.dev.js --open"
  },

开发环境运行npm run dev, 打包npm run build

最初

码字不易,若是对你有帮忙,那就点个赞吧

退出移动版