likes
comments
collection
share

使用webpack配置一个项目

作者站长头像
站长
· 阅读数 42

背景

身为一个前端开发人员,webpack几乎是我们日常项目开发必用的打包工具,但是因为职位或者不经常配置的原因,小编对其的了解一直模棱两可。在配置webpack的过程中磕磕绊绊,导致小编对配置webpack总是敬而远之,但是自己玩项目又离不开webpack打包工具,愁苦异常。今天痛定思痛,我决定自己研读webpack文档,辅之网上大神的一些文档,自己配置一个webpack的打包项目。 我的预期中项目使用的技术栈是 webpack(多页面打包),babel,less,vue 检测工具:eslint,prettier,husky,lint-stage。话不多说,开始实现。

1.前置工作

  • 先在本地安装个全局yarn?(小编喜欢使用yarn,并准备用这个进行接下来的配置)
  • 去github给自己搞个仓库,同步到本地?(学习和整理是必要的的,小编三年来看过好多资料,做过好多尝试,但是因为长期不用,又没有整理,导致那些知识吃了灰,又还给了搜索引擎😭)

2.webpack多页面项目初始化

文档 :webpack官网guide指南

  1. 拉取github的仓库地址(或者找一个空文件夹)
yarn init -y  // 初始化
yarn add webpack webpack-cli webpack-dev-server -D  // 安装webpack
yarn add webpack-merge html-webpack-plugin webpack-bundle-analyzer -D // 安装webpack配置合并 打包内容嵌入html 打包后文件分析相关
  1. 新建一个.gitignore文件 忽略node_modules dist

  2. 创建目录结构

使用webpack配置一个项目

  1. 新建src/public/index.html(打包生成的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><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
</body>
</html>
  1. 根目录新建一个webpack.config.js,配置webpack.config.js
const path = require("path");
const { merge } = require("webpack-merge"); // webpack配置合并  需要 yarn add webpack-merge -D

const HtmlWebpackPlugin = require("html-webpack-plugin"); // 打包html  需要 yarn add html-webpack-plugin -D
const BundleAnalyzerPlugin =
  require("webpack-bundle-analyzer").BundleAnalyzerPlugin; // 文件体积分析  需要 yarn add webpack-bundle-analyzer -D

const entryObj = {
  home: {
    title: "首页",
  },
  list: {
    title: "列表页",
  },
};

const getEntry = () => {
  const entry = {};
  Object.keys(entryObj).forEach(
    (v) => (entry[v] = `./src/pages/${v}/index.js`)
  );
  return entry;
};

const getHtmlWebpackPluginArr = () => {
  return Object.entries(entryObj).map(([key, val]) => {
    return new HtmlWebpackPlugin({
      title: val.title,
      filename: `${key}/index.html`,
      template: path.resolve(__dirname, "public/index.html"),
      chunks: [key, "common", "vendor"],
    });
  });
};

const commonConfig = {
  entry: getEntry(), // 入口文件配置  等价下方entry
  //   entry: {
  //     home: './src/pages/home/index.js',
  //     list: './src/pages/list/index.js',
  //   },  // 入口文件配置
  output: {
    filename: "[name]/index.js", // 打包文件名
    path: path.resolve(__dirname, "dist"), // 打包文件位置
    clean: true, // 每次打包前清空上次打包文件
  },
  module: {
    rules: [
      {
        test: /\.(png|svg|jpg|jpeg|gif)$/i,
        type: "asset/resource",
      }, // png等文件的处理
      {
        test: /\.(woff|woff2|eot|ttf|otf)$/i,
        type: "asset/resource",
      }, // 字体文件的处理
    ],
  },
  plugins: [
    ...getHtmlWebpackPluginArr(), // 多页面文件打包 等价下面
    // new HtmlWebpackPlugin({
    //   title: "home", // 打包生成html文件的title
    //   filename: `home/index.html`, // 打包生成html文件的位置和名字
    //   template: path.resolve(__dirname, "public/index.html"), // 打包使用的html模板
    //   chunks: ["home"], // html中引入的文件
    // }),
    // new HtmlWebpackPlugin({
    //   title: "list", // 打包生成html文件的title
    //   filename: `list/index.html`, // 打包生成html文件的位置和名字
    //   template: path.resolve(__dirname, "public/index.html"), // 打包使用的html模板
    //   chunks: ["list"], // html中引入的文件
    // }),
  ],
  optimization: {
    runtimeChunk: "single", // 运行时代码 // 将 runtime 代码拆分为一个单独的 chunk。将其设置为 single 来为所有 chunk 创建一个 runtime bundle
    splitChunks: {
      cacheGroups: {
        common: {
          name: "common",
          chunks: "initial",
          minSize: 1,
          priority: 0,
          minChunks: 2, // 同时引用了2次才打包
        }, // 多页面共用的文件
        vendor: {
          test: /[\\/]node_modules[\\/]/,
          name: "vendors",
          chunks: "all",
        }, // node_modules的打包文件
      },
    },
  },
};

const proConfig = {
  mode: "production",
  devtool: "source-map",
  plugins: [new BundleAnalyzerPlugin()],
};

const devConfig = {
  mode: "development",
  devtool: "inline-source-map",
  devServer: {
    hot: true, // 热更新
    open: ["/home"], // 默认打开home/index.html
    client: {
      overlay: {
        errors: true, // 有错误展示弹框
        warnings: false, // 警告不展示
      },
    },
  },
};

module.exports = (env) => {
  return merge(commonConfig, env.production ? proConfig : devConfig);
};

  1. 配置package.json 创建打包和启动服务命令
// package.json
"scripts": {
    "build": "webpack --env production",
    "start": "webpack-dev-server",
    "server": "webpack-dev-server"
  },

到此为止webpack多页面配置就简单完成了。可以去yarn build / yarn serve去尝试一下

3.webpack配置babel

webpack安装babel

  1. 安装babel相关
yarn @babel/core @babel/preset-env babel-loader -D // babel转换器 babel转换预设 webpack配置的babel-loader
  1. 配置bebel
// webpack.config.js  放在commonConfig中吧
{
    test: /\.js$/,
    use: {
      loader: "babel-loader",
    },
    exclude: "/node_modules/",
}, // 使用babel解析文件

新建 babel.config.js

module.exports = {
  presets: ["@babel/preset-env"],
};

package.json添加项目兼容的浏览器版本

"browserslist": [
    "defaults",
    "not ie < 11",
    "last 2 versions",
    "> 1%",
    "last 3 iOS versions"
  ],
 // 这个很多地方都用到,添加在package.json里面做一个统一
  1. 检测babel成果
const promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve(11111);
  }, 1000);
});

promise.then((data) => {
  console.log("data", data);
});

打包后转换
var promise = new Promise(function (resolve, reject) {
  setTimeout(function () {
    resolve(11111);
  }, 1000);
});
promise.then(function (data) {
  console.log("data", data);
});

本来想查看一下promise转换相关,但是看了一下现在浏览器兼容程度,应该是全兼容了,所以我的@babel-runtime 一直安装不上,估计是废弃了。至此,babel相关就完成了。

4.webpack配置解析less文件

# Webpack——打包CSS / Less / Sass资源相关配置

  1. 安装相关的包
yarn add css-loader less less-loader -D  // 解析css文件,less文件
yarn add mini-css-extract-plugin // 将css提出,压缩
yarn add postcss-loader autoprefixer -D  // 加前缀,兼容浏览器使用
  1. 进行配置
// webpack.config.js

const MiniCssExtractPlugin = require('mini-css-extract-plugin');

// modules rules
{
    test: /\.less$/i,
    use: [
      MiniCssExtractPlugin.loader,
      "css-loader",
      "less-loader",
      {
        loader: "postcss-loader",
        options: {
          postcssOptions: {
            plugins: [require("autoprefixer")],  // 添加前缀
          },
        },
      },
    ],
 }, // 处理less文件
 
// plugins
new MiniCssExtractPlugin({
  filename: "css/[name].css",
})
  1. 检测效果
div{
    height: 300px;
    display: flex;
    background-color: #ededed;
    border: 1px solid #333;
    border-radius: 5px;
    span{
        color: red;
    }
}

打包后 dist/css/home.css
div {
  height: 300px;
  background-color: #ededed;
  border: 1px solid #333;
  border-radius: 5px;
}
div span {
  color: red;
}

启动yarn start 有增加 display: flex 的前缀 ,less配置完成

5.webpack 配置使用vue

# 基于webpack从0配置vue开发

这个大神写的超级nice,跟着文档做起来还是很丝滑的,有一点需要注意的是 vue和vue-template-compiler的版本要保证一致奥,让我们操练起来。

  1. 装包
 yarn add vue@2.6.14 vue-template-compiler@2.6.14 vue-loader@15.9.8 -D
 // vue   解析vue模板  webpack使用的loder
  1. 配置

(1) 配置vue.config.js

// webpack.config.js

const { VueLoaderPlugin } = require('vue-loader');

// modules.rules
{
    test: /\.vue$/,
    use: [
        {
            loader: 'vue-loader',
            options: {
                compilerOptions: {
                    preserveWhitespace: false,
                },
            },
        },
    ],
},

// plugins
new VueLoaderPlugin()

(2)调整文件结构

src/home 下新建views文件夹 文件夹下面新建 App.vue

//App.vue

<template>
  <div>
    跟着大神 做
    <span>{{ msg }}</span>
    的码农
  </div>
</template>

<script>
export default {
  name: "App",

  data() {
    return {
      msg: "有追求的",
    };
  },
};
</script>
<style lang="less" scoped>
div {
  height: 300px;
  display: flex;
  background-color: #ededed;
  border: 1px solid #333;
  border-radius: 5px;
  span {
    color: red;
  }
}
</style>


(3)src/home文件夹下 删除 index.less, 修改index.js

import Vue from "vue";

import App from "./views/App.vue";

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

(4) 修改src/public/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><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
    //添加vue文件之后绑定的根元素
    <div id="app"></div> 
</body>
</html>
  1. yarn start 启动服务查看运行效果

使用webpack配置一个项目

恭喜恭喜,webpack配置vue跑通了,下一个eslint,prettier

6.webpack配置解析 eslint,prettier

# 前端代码规范实践指南(ESLint,Prettier,Husky...)

大佬写的好,看懂了,配成功了

  1. 安装eslint
yarn add eslint -D
  1. 控制台执行
npx eslint --init

使用webpack配置一个项目

  1. 新建.eslintignore
node_modules

dist
  1. 先不用处理报错,先添加prettier
yarn add prettier -D
yarn add eslint-plugin-prettier eslint-config-prettier -D  // 处理prettier 和 eslint冲突的方案

5.根目录创建.prettierrc.js文件

module.exports = {
    printWidth: 100, //一行的字符数,如果超过会进行换行,默认为80
    tabWidth: 4, //一个tab代表几个空格数,默认为80
    useTabs: false, //是否使用tab进行缩进,默认为false,表示用空格进行缩减
    semi: true, //行位是否使用分号,默认为true
    singleQuote: true, //字符串是否使用单引号,默认为false,使用双引号
};

6.创建.prettierignore 内容同.eslintignore

7.配置解决eslint和prettier冲突

// .eslintrc.js

module.exports = {
    env: {
        browser: true,
        commonjs: true,
        es2021: true,
    },
    extends: [
        'plugin:vue/essential',
        'standard',
        // 新增,必须放在最后面
        'plugin:prettier/recommended',  // 使eslint先解析 prettier的相关规则
    ],
    parserOptions: {
        ecmaVersion: 'latest',
    },
    plugins: ['vue'],
    rules: {},
};

8.在vscode设置setting.json使文件在保存的时候自动修复

//setting.json 添加

{
    "eslint.enable": true, //是否开启vscode的eslint
    "eslint.alwaysShowStatus": true,//是否在保存的时候自动fix eslint 
    "eslint.options": { //指定vscode的eslint所处理的文件的后缀
        "extensions": [
            ".js",
          	".vue",
          	".ts",
          	".tsx"
        ]
    },
    "eslint.validate": [ //确定校验准则
        "javascript",
    ],
    "editor.codeActionsOnSave": {
        "source.fixAll.eslint": true
    }
}

9.找一个文件ctrl + s 保存一下,嗯嗯,没问题。 package.json添加一个eslint命令

// package.json

"scripts": {
    "build": "webpack --env production",
    "start": "webpack-dev-server",
    "server": "webpack-dev-server",
    "lint": "eslint ./src --fix"  // eslint格式化src下面的所有文件 (存量代码eslint格式化一下,总不能一个一个页面保存吧,哈哈)
},

eslint + prettier配置完成,要添加其他的规则,就在rules额外添加(再次声明大神的文章丝滑,易懂)

7.webpack配置husky和lintstaged

# 前端代码规范实践指南(ESLint,Prettier,Husky...)

  1. 作用和目的 在git提交流程中加入 eslint的相关检测(防止其他的同学的未被eslint格式化的代码提交到代码仓库)
  2. 安装和配置
// 需要在git项目中  不是远端仓库拉下来的代码,需要先 git init一下

1.//安装husky
yarn add husky -D

2.//添加 prepare 命令
npm set-script prepare "husky install"

3.// prepare 创建 bash 脚本,安装 git hooks
npm run prepare

4.// 添加 pre-commit 的 git hook 脚本
npx husky add .husky/pre-commit "npx eslint src --fix"


// 配置只格式化新开发的代码,不去格式化以前的代码

5.//安装 lint-taged
yarn add lint-staged -D

6.// 新建.lintstagedrc.js 配置文件,
module.exports = {
  '**/*.{ts,tsx,js,jsx}': [
    "eslint --cache --fix",
  ],
  "**/*.vue": [
    "eslint --cache --fix",
  ]
}

7.// 刚刚创建的 `./.husky/pre-commit` 里改成执行 `lint-staged` 命令:
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

npx lint-staged

大佬写的好详细,直接借用了(亲测可以)

小结

至此webpack配置项目已经完成了,有机会在搞个vue-cli配置,到时候跟大家一起请教探讨。 献上我的代码仓库,大家有兴趣可以下下来看看,有错误的地方希望大家提出指正。

文章代码仓库

参考文章

转载自:https://juejin.cn/post/7176242819248422973
评论
请登录