Webpack4

webpack开篇

什么是webpack

webpack是一套基于 NodeJS 的"模块打包工具",在webpack刚推出的时候就是一个单纯的JS模块打包工具,可以将多个模块的JS文件合并打包到一个文件中,但是随着时间的推移、众多开发者的追捧和众多开发者的贡献,现在webpack不仅仅能够打包JS 模块 , 还可以打包 CSS/LESS/SCSS/ 图片 等其它文件;

为什么要分模块

如果将所有的JS代码都写到一个文件中, 十分不利于代码的维护和复用,所以我们可以将不同的功能写到不同的模块中, 这样就提升了代码的维护性和复用性,但是当将代码写到不同模块时新的问题又出现了;

例如

  • 导入资源变多了, 请求次数变多了, 网页性能也就差了;

例如

  • 不同功能都放到了不同模块中了, 那么如何维护模块之间的关系也变成一个难题了;
<script src="./header.js"></script>
<script src="./content.js"></script>
<script src="./index.js"></script>
<script src="./footer.js"></script> // 如果index.js中用到了footer,就会报错

例如

... ...

如何解决上述问题

  • 项目上线时将用到的所有模块都合并到一个文件中;

  • 在index.html中只导入主文件, 再主文件中再导入依赖模块;

如何通过webpack来打包JS模块

  1. 安装webpack
npm init -y
npm install --save-dev webpack
npm install --save-dev webpack-cli
  1. 在终端中输入打包的指令
npx webpack index.js

注意点

  • index.js就是需要打包的文件;
  • 打包之后的文件会放到 dist 目录中, 名称叫做 main.js;

webpack配置文件

什么是webpack配置文件?

  • 我们在打包JS文件的时候需要输入: npx webpack index.js
  • 这句指令的含义是: 利用 webpack 将 index.js 和它依赖的模块打包到一个文件中
  • 其实在 webpack 指令中除了可以通过命令行的方式告诉 webpack 需要打包哪个文件以外
  • 还可以通过配置文件的方式告诉 webpack 需要打包哪个文件

webpack常见配置

属性名 作用
entry 需要打包的文件
output 打包之后输出路径和文件名称
mode 打包模式 development/production
development 不会压缩打包后的JS代码
production 会自动压缩打包后的JS代码

webpack.config.js

const path = require("path");

module.exports = {
    /*
    mode: 指定打包的模式, 模式有两种
    一种是开发模式(development): 不会对打包的JS代码进行压缩
    还有一种就是上线(生产)模式(production): 会对打包的JS代码进行压缩
    * */
    mode: "development", // "production" | "development"
    /*
    entry: 指定需要打包的文件
    * */
    entry: "./index.js",
    /*
    output: 指定打包之后的文件输出的路径和输出的文件名称
    * */
    output: {
        /*
        filename: 指定打包之后的JS文件的名称
        * */
        filename: "bundle.js",
        /*
        path: 指定打包之后的文件存储到什么地方
        * */
        path: path.resolve(__dirname, "bundle")
    }
};

webpack配置文件注意点

webpack配置注意事项

  • 配置文件的名称必须叫做: webpack.config.js , 否则直接输入 npx webpack 打包会出错
  • 如果要使用其它名称, 那么在输入打包命令时候必须通过 --config 指定配置文件名称
  • npx webpack --config xxx

打包命令简化

  • 每次输入npx webpack --config xxx 来打包文件会有一点蛋疼, 所以我们可以通过 npm script 来简化这个操作

webpack-sourcemap

什么是sourcemap?

  • webpack 打包后的文件会自动添加很多代码, 在开发过程中非常不利于我们去调试
  • 因为如果运行 webpack 打包后的代码,错误提示的内容也是打包后文件的内容
  • 所以为了降低调试的难度, 提高错误代码的阅读性, 我们就需要知道打包后代码和打包之前代码的映射关系
  • 只要有了这个映射关系我们就能很好的显示错误提示的内容, 存储这个映射关系的文件我们就称之为 sourcemap

如何开启sourcemap

属性名 作用 优势 缺点
eval 不会单独生成 sourcemap 文件, 会将映射关系存储到打包的文件中, 并且通过 eval 存储 性能最好 业务逻辑比较复杂时候提示信息可能不全面不正确
source-map 会单独生成 sourcemap 文件, 通过单独文件来存储映射关系 提示信息全面,可以直接定位到错误代码的行和列 打包速度慢
inline 不会单独生成 sourcemap 文件, 会将映射关系存储到打包的文件中, 并且通过 base64 字符串形式存储
cheap 生成的映射信息只能定位到错误行不能定位到错误列
module 不仅希望存储我们代码的映射关系, 还希望存储第三方模块映射关系, 以便于第三方模块出错时也能更好的排错

企业开发配置

属性名 作用
development: cheap-module-eval-source-map 只需要行错误信息, 并且包含第三方模块错误信息, 并且不会生成单独sourcemap 文件
production: cheap-module-source-map 只需要行错误信息, 并且包含第三方模块错误信息, 并且会生成单独sourcemap 文件

webpack-file-loader

什么是loader?

  • webapck 的本质是一个模块打包工具, 所以 webpack 默认只能处理 JS 文件,不能处理其他文件
  • 因为其他文件中没有模块的概念, 但是在企业开发中我们除了需要对 JS 进行打包以外
  • 还有可能需要对 图片/CSS 等进行打包, 所以为了能够让 webpack 能够对其它的文件类型进行打包
  • 在打包之前就必须将其它类型文件转换为 webpack 能够识别处理的模块
  • 用于将其它类型文件转换为 webpack 能够识别处理模块的工具我们就称之为 loader

如何使用loader

  • webpack 中的 loader 都是用 NodeJS 编写的, 但是在企业开发中我们完全没有必要自己编写
  • 因为已经有众多大神帮我们编写好了企业中常用的 loader , 我们只需要安装、配置、使用即可

通过npm安装对应的loader

  1. 按照 loader 作者的要求在 webpack 进行相关配置
  2. 使用配置好的 loader

fileloader使用

安装file-loader

npm install --save-dev file-loader

在 webpack.config.js 中配置 file-loader

module: {
    rules: [
      {
        test: /\.(png|jpg|gif)$/,
        use: [
          {
            loader: 'file-loader',
            options: {}
          }
        ]
      }
    ]
  }

webpack-file-loader 其它配置

注意点

  • 默认情况下 fileloader 生成的图片名就是文件内容的 MD5 哈希值

  • 如何想打包后不修改图片的名称, 那么可以新增配置 name: "[name].[ext]"

  • 其它命名规则详见: placeholders

  • 默认情况下 fileloader 会将生成的图片放到 dist 根目录下面

  • 如果想打包之后放到指定目录下面, 那么可以新增配置 outputPath: "images/"

  • 如果需要将图片托管到其它服务器, 那么只需在打包之前配置 publicPath: "托管服务器地址" 即可

webpack-url-loader

url loader

  • url-loader 功能类似于 file-loader
  • 但是在文件大小(单位 byte)低于指定的限制时,可以返回一个 DataURL

url loader 使用

url loader 安装

npm install --save-dev url-loader

url loader 配置

{
    test: /\.(png|jpg|gif)$/,
    use: [
        {
            loader: 'url-loader',
            options: {
                name: "[name].[ext]",
                outputPath: "/images",
                limit: 1024
            }
        }
    ]
}

url loader 优势

  • 图片比较小的时候直接转换成 base64 字符串图片, 减少请求次数
  • 图片比较大的时候由于生成的 base64 字符串图片也比较大, 就保持原有的图片

webpack-css-loader

css-loader

和图片一样 webpack 默认能不能处理 CSS 文件, 所以也需要借助 loader 将 CSS 文件转换为 webpack 能够处理的类型。

css-loader 使用

① 安装 css-loader

npm install --save-dev css-loader

② 安装 style-loader

npm install style-loader --save-dev

③ 配置 css-loader

{
    test: /\.css$/,
    use: [ 'style-loader', 'css-loader' ]
}

css-loader 和 style-loader 作用

loaderName 作用
css-loader 解析 css 文件中的 @import 依赖关系
style-loader webpack 处理之后的内容插入到 HTMLHEAD 代码中

css-loader 注意点

  • loader 特点
    • 单一原则, 一个 loader 只做一件事情
    • 多个 loader 会按照从 , 从 的顺序执行
  • 例如:从右至左
    • [ 'style-loader', 'css-loader' ]
    • 先执行 css-loader 解析 css 文件关系拿到所有内容
    • 再执行 style-loader 将内容插入到 HTML 的 HEAD 代码中
  • 例如: 从下至上
    • [{
      loader: "style-loader"
      },{
      loader: "css-loader"
      }]
    • 先执行 css-loader 解析 css 文件关系拿到所有内容
    • 再执行 style-loader 将内容插入到 HTML 的 HEAD 代码中

ES6-Module

ES6 模块化

  • 在 ES6 出现之前,JS 不像其他语言拥有 模块化 这一概念,于是为了支持 JS 模块化
  • 我们使用类、立即执行函数或者第三方插件 (RequireJS、seaJS) 来实现模块化
  • 但是在 ES6 出现之后, 上述解决方案都已经被废弃, 因为 ES6 中正式引入了模块化的概念
  • ES6 模块化模块和 NodeJS中一样, 一个文件就是一个模块, 模块中的数据都是私有的
  • ES6 模块化模块和 NodeJS 中一样, 可以通过对应的关键字暴露模块中的数据,可以通过对应的关键字导入模块, 使用模块中暴露的数据

ES6 模块化使用

  • 常规导出
  • 分开 导入 导出
export xxx;
import {xxx} from "path";
  • 一次性 导入 导出
export {xxx, yyy, zzz};
import {xxx, yyy, zzz} from "path";
  • 注意点
    • 接收 导入变量名 必须和 导出变量名 一致
    • 如果想修改 接收变量名 可以通过 xxx as newName 方式
    • 变量名 被修改后原有 变量名 自动失效
  • 默认 导入 导出
export default xxx;
import xxx from "path";
  • 注意点
    • 一个 模块 只能 使用一次 默认 导出, 多次 无效
    • 默认 导出时, 导入的名称 可以和 导出的名称 不一致
  • 示例
/*
ES6模块化的第一种方式
导出数据: export {xxx};
导入数据: import {xxx} from "path";
* */
/*
注意点:
1.如果是通过export {xxx};方式导出数据, 那么在导入接收的时候接收的变量名称必须和导出的名称一致
  究其原因是因为在导入的时候本质上是ES6的解构赋值
2.如果是通过export {xxx};方式导出数据, 又想在导入数据的时候修改接收的变量名称, 那么可以使用as来修改
  但是如果通过as修改了接收的变量名称, 那么原有的变量名称就会失效
* */
/*
// import {name} from "./a.js";
import {str} from "./a.js";

console.log(str);
 */
/*
let obj = {
    name: "xhh",
    age: 18
};
// let {name, age} = obj;
// console.log(name);
let {str, age} = obj;
console.log(str);
console.log(age);
 */
/*
import {name as str} from "./a.js";

console.log(name);
console.log(str);
 */


/*
ES6模块化的第二种方式
导出数据: export default xxx;
导入数据: import xxx from "path";
* */
/*
注意点:
1.如果是通过export default xxx;导出数据, 那么在接收导出数据的时候变量名称可以和导出的明白不一致
2.如果是通过export default xxx;导出数据, 那么在模块中只能使用一次export default
* */
/*
// import name from "./b.js";
import str from "./b.js";

console.log(str);
 */
/*
import name from "./b.js";
import age from "./b.js";
console.log(name);
console.log(age);
 */
/*
import {name, age} from "./a.js";

console.log(name);
console.log(age);
 */

/*
// 两种方式混合使用
import Person,{name, age, say} from "./c.js";
let p = new Person();
console.log(p);

console.log(name);
console.log(age);
say();
 */

// const icon = require("./xhh.jpg");
// const _ = require("./index.css");

import icon from "./xhh.jpg";
import "./index.css";

let oImg = document.createElement("img");
oImg.src = icon;
oImg.setAttribute("class", "size");
document.body.appendChild(oImg);

webpack-less-loader

less-loader

自动将 less 转换为 CSS。

less-loader 使用

① 安装 less

npm install --save-dev less

② 安装 less-loader

npm install --save-dev less-loader

③ 配置 less-loader

{
    test: /\.less$/,
    use: [{
        loader: "style-loader"
    }, {
        loader: "css-loader"
    }, {
        loader: "less-loader"
    }]
}

📖 注意点

  • 因为 loader 是从 右 至 左 从 下 至 上,所以必须先由 less-loader 处理往后才能交给其他 loader 处理

webpack-sass-loader

scss-loader

🧀 自动将 scss 转换为 css

scss-loader 使用

① 安装 scss

npm install --save-dev node-sass

② 安装 scss-loader

npm install --save-dev sass-loader

③ 配置 scss-loader

{
  test: /\.scss$/,
  use: [{
      loader: "style-loader" // 将 JS 字符串生成为 style 节点
  }, {
      loader: "css-loader" // 将 CSS 转化成 CommonJS 模块
  }, {
      loader: "sass-loader" // 将 Sass 编译成 CSS
  }]
}

📖 注意点

  • 因为 loader 是从右 至左 从下 至上,所以必须先由 sass-loader 处理往后才能交给其他 loader 处理

webpack-postcss-loader

什么是 PostCSS ?

  • 官方文档
  • PostCSS 和 sass/less 不同, 它不是 CSS 预处理器
  • PostCSS 是一款使用插件去转换 CSS 的工具
  • PostCSS 有许多非常好用的插件
  • 例如
    • autoprefixer (自动 补全 浏览器 前缀)
    • postcss-pxtorem (自动把 px 代为转换成 rem )
    • ... ...

使用 PostCSS 自动补全浏览器前缀

① 安装 postcss-loader

npm i -D postcss-loader

② 安装需要的插件

npm i -D autoprefixer

③ 配置 postcss-loader

  • 在 css-loader or less-loader or sass-loader 之前添加 postcss-loader

④ 创建 postcss-loader 配置文件

⑤ 在配置文件中配置 autoprefixer

module.exports = {
    plugins: {
        "autoprefixer": {
            "overrideBrowserslist": [
                // "ie >= 8", // 兼容IE7以上浏览器
                // "Firefox >= 3.5", // 兼容火狐版本号大于3.5浏览器
                // "chrome  >= 35", // 兼容谷歌版本号大于35浏览器,
                // "opera >= 11.5" // 兼容欧朋版本号大于11.5浏览器,
                "chrome  >= 36", // 如果需要适配的浏览器完全兼容则不会添加前缀
            ]
        }
    }
};

使用 PostCSS 自动将 px 转换成 rem

  • 文档

  • 安装 postcss-pxtorem

npm install postcss-pxtorem -D

在配置文件中配置 postcss-pxtorem

"postcss-pxtorem": {
        rootValue: 100, // 根元素字体大小
        // propList: ['*'] // 可以从px更改到rem的属性
        propList: ["height"]
}
属性名 作用
rootValue (Number) root 元素的字体大小。
unitPrecision (Number) 允许 REM 单位增长到的十进制数。
propList ( array ) 可以从 px 更改到 rem 的属性。
值需要精确匹配。
使用通配符 * 启用所有属性。 示例:['*']
在单词的开头或者结尾使用 *。 ( ['*position*'] 将匹配 background-position-y )
使用 与属性不匹配。! 示例:['*','letter-spacing']!
将"非"前缀与其他前缀合并。 示例:['*','font*']!
属性名 作用
selectorBlackList ( array ) 要忽略和离开的选择器。
如果值为字符串,它将检查选择器是否包含字符串。
['body'] 将匹配 .body-class
如果值为 regexp,它将检查选择器是否匹配正则表达式。
[/^body$/] 将匹配 body,但不匹配 .body
属性名 作用
replace (Boolean) 替代包含 rems 的规则,而不是添加回退。
mediaQuery (Boolean) 允许在媒体查询中转换 px。
minPixelValue (Number) 设置要替换的最小像素值。

突然感觉淡淡不忧伤了, 过去麻烦的事 webpack 都帮我们做完了

webpack-css-loader模块化

默认情况下 通过 import "./xxx.css" 导入的样式 是 全局样式

也就是 只要 被导入, 在其它 文件中 也可以 使用

如果想要导入的 CSS 文件只在 导入 的 文件中 有效, 那么就需要开启 CSS 模块化

{
    loader: "css-loader",
    options: {
        modules: true // 开启CSS模块化
    }
}

然后在 导入 的 地方 通过 import xxx from "./xxx.css" 导入

然后在使用的地方通过 xxx.className 方式使用即可

webpack-iconfont-loader

如何打包字体图标

字体图标中也用到了 url 用到了文件, 所以我们需要通过 file-loader 来处理字体图标文件

{
    test: /\.(eot|svg|ttf|woff|woff2)$/,
    use:[{
        loader: "file-loader",
        options: {
            name: "[name].[ext]",
            outputPath: "font/",
        }
    }]
}

webpack-html-plugin

什么是插件 (plugin) ?

plugin 用于扩展 webpack 的功能。

当然 loader 也是变相的扩展了 webpack ,但是它只专注于转化文件这一个领域。

而 plugin 的功能更加的丰富,而不仅局限于资源的加载。

什么是 HtmlWebpackPlugin ?

HtmlWebpackPlugin 会在打包结束之后自动创建一个 index.html , 并将打包好的 JS 自动引入到这个文件中。

HtmlWebpackPlugin 使用

官方文档

  • 安装 HtmlWebpackPlugin
npm install --save-dev html-webpack-plugin
  • 配置 HtmlWebpackPlugin
const HtmlWebpackPlugin = require('html-webpack-plugin');
plugins: [new HtmlWebpackPlugin()]

webpack-clean-plugin

什么是 clean-webpack-plugin ?

webpack-clean-plugin 会在打包之前 将我们指定的文件夹清空

应用场景 每次打包前 将dist 目录清空, 然后再存放 新打包的内容, 避免 新老混淆问题

clean-webpack-plugin 使用

npm install --save-dev clean-webpack-plugin
  • 配置 clean-webpack-plugin
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
plugins: [new CleanWebpackPlugin()]

posted @ 2020-02-21 14:20  Leader_TBlog  阅读(155)  评论(0编辑  收藏  举报