初识webpack三

56 阅读5分钟

一、js语法检查

语法检查:eslint-loader eslint

只检查自己写的源代码,第三方的库时不用检查的

设置检查规则:

package.json中eslintConfig中设置

"eslintConfig":{
    "extends":"airbnb-base"
},

airbnb-->需要下载这些包

eslint-config-airbnb-base  eslint-plugin-import  eslint-webpack-plugin eslint

也可以单独新建一个.eslintrc.js文件配置,配置如下:

module.exports = {
  env: {
    browser: true,
    es6: true,
    node: true,
  },
  extends: "eslint:recommended",
  parserOptions: {
    ecmaVersion: 2015,
    sourceType: "module",
  },
  rules: {
    // 缩进
    indent: [
      "error",
      4, //我的是编辑器自动格式化,不是使用tabs,而是四个空格
    ],
    "linebreak-style": ["error", "windows"],
    // 引号
    quotes: [1, "single"],
    // 分号结尾
    semi: ["error", "always"],
    "no-unused-vars": [
      2,
      {
        // 允许声明未使用变量
        vars: "local",
        // 参数不检查
        args: "none",
      },
    ],
    // 最大空行100
    "no-multiple-empty-lines": [0, { max: 100 }],
    "no-mixed-spaces-and-tabs": [0],
    //不能使用console
    "no-console": "off",
    //未定义变量不能使用
    "no-undef": 0,
    //一行结束后面不要有空格
    "no-trailing-spaces": 1,
    //强制驼峰法命名
    camelcase: 2,
    //对象字面量项尾不能有逗号
    "comma-dangle": [2, "never"],
    //this别名
    "consistent-this": [2, "that"],
  },
};

webpack.config.js配置如下:

const { resolve } = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const ESLintPlugin = require("eslint-webpack-plugin");
module.exports = {
  entry: "./src/js/index.js",
  output: {
    filename: "js/built.js",
    path: resolve(__dirname, "build"),
  },
  module: {
    rules: [
     
      {
        test: /\.js$/,
        exclude: /node_modules/, //一定要排除node_modules
        // loader: "eslint-loader",
        // options: {
        //   //  自动修复
        //   fix: true,
        // },
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: "./src/index.html",
    }),
    new ESLintPlugin({ fix: true }),
  ],
  mode: "development",
};

二、js兼容处理

js兼容处理需下载如下几个包:

npm i babel-loader @babel/preset-env @babel/core @babel/polyfill core-js -D
  • 基本js兼容性处理-->@babel/preset-env
  • 问题:只能转换基本语法,如promise高级语法不能转换
    
  • 全部js兼容性处理 -->@babel/polyfill
  • 问题:我只要解决部分兼容性问题,但是将所有兼容性代码全部引入,体积太大了
    
  • 需要做兼容性处理的就做按需加载-->core-js

webpack.config.js配置如下:

const { resolve } = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const ESLintPlugin = require("eslint-webpack-plugin");
module.exports = {
  entry: "./src/js/index.js",
  output: {
    filename: "js/built.js",
    path: resolve(__dirname, "build"),
  },
  module: {
    rules: [
      {
        test: /.\js$/,
        exclude: /node_modules/,
        loader: "babel-loader",
        options: {
          // 预设:指示babel做怎么样的兼容性处理
          presets: [
            [
              "@babel/preset-env",
              {
                // 按需加载
                useBuiltIns: "usage",
                // 指定core-js版本
                corejs: {
                  version: 3,
                },
                // 指定兼容性做到哪个版本浏览器
                targets: {
                  chrome: "60",
                  firefox: "60",
                  ie: "9",
                  safari: "10",
                },
              },
            ],
          ],
        },
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: "./src/index.html",
    }),
    new ESLintPlugin({ fix: true }),
  ],
  mode: "development",
};

三、js压缩

js压缩只需要将mode配置为'production'就可自动压缩js了

webpack.config.js配置如下:

const { resolve } = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const ESLintPlugin = require("eslint-webpack-plugin");
module.exports = {
  entry: "./src/js/index.js",
  output: {
    filename: "js/built.js",
    path: resolve(__dirname, "build"),
  },

  plugins: [
    new HtmlWebpackPlugin({
      template: "./src/index.html",
    }),
    new ESLintPlugin({ fix: true }),
  ],
  // 生产环境下自动压缩js
  mode: "production",
};


四、html压缩

html压缩可以在html-webpack-plugin插件中配置:

下载html-webpack-plugin插件

npm i html-webpack-plugin -D

webpack.config.js配置如下:

const { resolve } = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const ESLintPlugin = require("eslint-webpack-plugin");
module.exports = {
  entry: "./src/js/index.js",
  output: {
    filename: "js/built.js",
    path: resolve(__dirname, "build"),
  },

  plugins: [
    new HtmlWebpackPlugin({
      template: "./src/index.html",
      // 压缩html代码
      minify: {
        // 移除空格
        collapseWhitespace: true,
        // 移除注释
        removeComments: true,
      },
    }),
    new ESLintPlugin({ fix: true }),
  ],
  mode: "production",
};

五、HMR热模块替换

HMR:hot module replacement 热模块替换 /模块热替换

作用:一个模块发生变化,只会重新打包这一个模块(而不是打包所有模块) 极大提升构建速度

  • 样式文件:可以使用HMR功能:因为style-loader内部实现了

  • js文件:默认不能使用HMR功能-->需要修改js代码,添加支持HMR功能的代码

  • 注意:HMR功能对js的处理,只能处理非入口的js文件

  • html文件:默认不能使用HMR功能,同时会导致html文件不能热更新(不用做HMR功能)

  • 解决:修改entry入口,将html文件引入

  • 开启HMR只需将devServer中的hot设置为true即可

webpack.config.js配置如下

const { resolve } = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
  entry: ["./src/js/index.js", "./src/index.html"],
  output: {
    filename: "js/built.js",
    path: resolve(__dirname, "build"),
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ["style-loader", "css-loader"],
      },
      // 注意:安装less-loader时要一起安装less
      {
        test: /\.less$/,
        use: ["style-loader", "css-loader", "less-loader"],
      },
     
      // 处理html中img资源
      {
        test: /\.html$/,
        loader: "html-loader",
      },
      // 打包其他资源(除了html/js/css资源以外的其他资源)
      {
        // 排除css/js/html资源
        exclude: /\.(css|js|html|less|jpg|png|gif)$/,
        loader: "file-loader",
        type: "javascript/auto",
        options: {
          name: "[hash:9].[ext]",
          esModule: false,
          outputPath: "media",
        },
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: "./src/index.html",
    }),
  ],
  mode: "development",
  // 开发服务器 devServer :用来自动化(自动编译,自动打开浏览器,自动刷新浏览器)
  // 特点:只会在内存中编译打包,不会有任何输出
  // 启动devServer指令: webpack server   
  devServer: {
    static: resolve(__dirname, "build"),
    // contentBase: resolve(__dirname, "build"),
    // 启动gzip压缩
    compress: true,
    //端口号
    port: 3000,
    // 自动打开浏览器
    open: true,
    // 开启HMR功能, 热替换
    // 当修改了webpack配置,新配置要想生效,必须重启webpack服务
    hot: true,
    
  },
};

对js文件实现HMR功能: 创建一个print.js文件

console.log("print.js打印");

function print() {
  console.log("hello print");
}

export default print;

在index.js文件中监听print.js的变化

import "../css/iconfont.css";
import "../css/index.less";
import print from "./print.js";
function add(x, y) {
  return x + y;
}
console.log(add(1, 2));
print();

if (module.hot) {
  // 一旦 module.hot 为true,说明开启了HMR功能。-->让hmr功能代码生效
  module.hot.accept("./print.js", function () {
    // 方法会监听print.js文件的变化,一旦发生变化,其他模块不会重新打包构建
    // 会执行后面的回调函数
    print();
  });
}

六、sourcemap

source-map:一种 提供源代码到构建后代码映射 技术(如果构建后代码出错了,通过映射可以追踪到源代码错误) 配置source-map可通过devtool设置

devtool: "eval-source-map"

说明:

    [inline-|hidden-|eval-][nosources-][cheap-[module-]]source-map

source-map:外部

 错误代码准确信息和源代码的错误位置

inline-source-map:内联

   只生产一个内联source-map     
   错误代码准确信息和源代码的错误位置
 

hidden-source-map:外部

 错误代码错误原因,但是没有错误位置
 不能追踪源代码错误,只能提示到构建后代码的错误位置

eval-source-map:内联

每一个文件都生产对应的source-map,都在eval
错误代码准确信息和源代码的错误位置

nosources-source-map:外部

错误代码准确信息,但是没有任何源代码信息

cheap-source-map:外部

错误代码准确信息和源代码的错误位置
只能精确到行

cheap-module-source-map:外部

错误代码准确信息和源代码的错误位置
module会将loader的source map加入

内联和外部的区别:1、外部生产了文件,内联没有 2、内联构建速度更快

开发环境:速度快,调试更友好

速度快(eval>inline>cheap>...)
    eval-cheap-source-map
    eval-source-map
调试更友好
    source-map(行+列)
    cheap-module-source-map(行)
    cheap-source-map
-->eval-source-map推荐使用 /eval-cheap-module-source-map

生产环境:源代码要不要隐藏?调试要不要更友好

  内联会让代码体积变大,所以在生产环境不用内联

隐藏代码:

    nosources-source-map 全部隐藏
    hidden-source-map 只隐藏源代码,会提示构建后代码错误信息

调试:

-->source-map/cheap-module-source-map

webpack.config.js配置如下:


const { resolve } = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
  entry: ["./src/js/index.js", "./src/index.html"],
  output: {
    filename: "js/built.js",
    path: resolve(__dirname, "build"),
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ["style-loader", "css-loader"],
      },
      // 注意:安装less-loader时要一起安装less
      {
        test: /\.less$/,
        use: ["style-loader", "css-loader", "less-loader"],
      },
      {
        test: /\.(jpg|png|gif)$/,
        loader: "url-loader",
        type: "javascript/auto",
        options: {
          limit: 8 * 1024,
          name: "[hash:10].[ext]",
          esModule: false,
          outputPath: "imgs",
        },
      },
      // 处理html中img资源
      {
        test: /\.html$/,
        loader: "html-loader",
      },
      // 打包其他资源(除了html/js/css资源以外的其他资源)
      {
        // 排除css/js/html资源
        exclude: /\.(css|js|html|less|jpg|png|gif)$/,
        loader: "file-loader",
        type: "javascript/auto",
        options: {
          name: "[hash:9].[ext]",
          esModule: false,
          outputPath: "media",
        },
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: "./src/index.html",
    }),
  ],
  mode: "development",
  devServer: {
    static: resolve(__dirname, "build"),
    // contentBase: resolve(__dirname, "build"),
    // 启动gzip压缩
    compress: true,
    //端口号
    port: 3000,
    // 自动打开浏览器
    open: true,
    // 开启HMR功能, 热替换
    // 当修改了webpack配置,新配置要想生效,必须重启webpack服务
    hot: true,
    // host: "localhost",
  },
  //配置sourcemap
  devtool: "eval-source-map",
  
};