webpack 开发环境一次搞定

前言

一句话说明本文主要介绍什么

分享webpack 开发环境中都需要配置什么?

使用 html-webpack-plugin 产生 index.html

plugins是个阵列,因此我们可以配置多个不同的插件:

npm install html-webpack-plugin -D
复制代码
// ./demos/auto-create-html/webpack.config.js

...

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

module.exports = {
   ...
    plugins: [
        new HtmlWebpackPlugin()
    ]
}
复制代码

配置改变时自动重新建置

由于 Dev Server 的监听范围仅限专案的内容,并不包括其他的档案,因此在上节加上 html-webpack-plugin 的时候,我们修改了 webpack.config.js ,但是并不会重新建置。

这时就需要 nodemon 的帮助,这是一个可以侦测 node.js 程式并自动重载的工具,首先先安装:

npm install nodemon -D
复制代码
// ./demos/reload-config/package.json
{
  "name": "development-mode",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "scripts": {
    "dev": "nodemon --watch webpack.config.js ./node_modules/.bin/webpack-dev-server"
  },
  "devDependencies": {
    "html-webpack-plugin": "^4.5.0",
    "nodemon": "^2.0.4",
    "webpack": "^4.44.2",
    "webpack-cli": "^3.3.12",
    "webpack-dev-server": "^3.11.0"
  },
  "dependencies": {
    "lodash": "^4.17.20"
  }
}
复制代码

Hot Module Replacement

前面的例子虽然在修改档案后会更新浏览器,但如果只是一小部分的修改,就让整个网页重整,会消耗不必要的资源,因此 Dev Server 提供了模组热替换的功能,它能在不重整整个网页的情况下,更新一小部分的内容。

首先要开启 devServer.hot:

/ ./demos/hmr/webpack.config.js---------------模组热替换-------------------------------

...

module.exports = {
    ...
    devServer: {
        hot: true
    },
    ...
}
复制代码

使用 webpack 开发 JavaScript

  • @babel/core: Babel 的核心库,只负责建置的流程,并不会加上转换的处理,这部分是属于 Plugins 的职责。
  • @babel/cli: Babel 的 CLI 工具,可以下指令控制 Babel 的执行
  • @babel/preset-env:每个 Plugins 都针对特定的语法处理,假设使用了其他的语法,就必须要个别加上对应的 Plugins ,设定会变得相当复杂,所幸 Babel 提供了 Presets ,Presets 会将多个 Plugins 包起来,供使用者引入所需的 Plugins 。
  • Polyfill:Babel 的 Plugins 只负责转换语法,并没有对新的语意做解释,这时就要藉由 Polyfill 的帮助。
npm install @babel/core @babel/cli -D
npm install @babel/preset-env -D
npm install core-js
复制代码
// ./demos/babel-preset/babel.config.js
module.exports = {
  presets: ["@babel/preset-env"],
};
复制代码
// ./demos/babel-polyfill/babel.config.js
module.exports = {
  presets: [
    [
      "@babel/preset-env",
      {
        useBuiltIns: "usage",
        corejs: 3,
      },
    ],
  ],
};
复制代码
  • useBuiltIns: 决定要如何引入 Polyfill

    • false: 预设值,全部手动引入
    • 'entry': 在入口 .js 档中引入完整的core-js,Babel 会依照环境配置取出对应的 Polyfill
    • 'usage': Babel 会侦测代码,以引入对应的 Polyfill
  • corejs:指定 core-js 版本

这里配置使用 usage 的方式自动引入 Polyfill 。

将 Babel 加到 webpack 中

使用 babel-loader 将 babel 引入 webpack 的建置流程中:

// ./demos/babel-webpack/webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /\.js$/,
        use: {
          loader: "babel-loader",
        },
      },
    ],
  },
};
复制代码

小结:

  1. 在真实的环境中,虽然 webpack 可以识别 ES2015 的语法,但是浏览器不一定懂,因此还是需要利用 Babel 做转换。

  2. Babel 本身不会做任何的转换,需要加上对应的 Plugins 才会有转换的动作,而 Preset 可以将多个 Plugins 包起来,依照目标环境做对应的转换。

  3. Plugins 只会转换语法,对于新的语意并不会转换,这时需要藉由 core-js 的 Polyfill 帮助做转换。

  4. 使用 babel-loader 引入 Babel 至 webpack 的建置流程中,让我们在建置过程中享有 Babel 的功能。

使用webpack处理Style

使用 CLI 设定Style

  • postcss: PostCSS 的核心库,负责建置流程
  • postcss-cli: PostCSS 的 CLI 工具,供使用者使用 CLI 执行 PostCSS
  • 使用 postcss-preset-env 转换代码 :现在我们想要将拥有新语法的 .css 内容转为旧版本相容的语法,这时就可以藉由 PostCSS 的postcss-preset-envPlugin
npm install postcss postcss-cli -D
npm install postcss-preset-env -D
cmd执行postcss src/style.css --dir dist --use postcss-preset-env
复制代码

使用配置档设定 PostCSS

使用 CLI 设定虽然简单,但只要配置复杂,就会变得难以维护,因此 PostCSS 提供了配置档的方式做设定:

// ./demos/postcss-config/postcss.config.js
module.exports = {
  map: true,
  plugins: [require("postcss-preset-env")()],
};
复制代码

使用 .browserslistrc 配置目标环境

预设 postcss-preset-env 会将目标对象视为 browserslist 的 defaults 值

我们可以自己使用 .browserslistrc 做目标的调整:

// ./demos/postcss-browserslist/.browserslistrc
> 5%
复制代码

重新建置后会发现,变数没有做转换了,这是因为在范围内的浏览器都已经支援 css 变数的语法。

将 CSS 载入至 Webpack 中

npm install postcss-loader -D
复制代码
// ./demos/postcss-loader/webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          {
            loader: "postcss-loader",
          },
        ],
      },
    ],
  },
};
复制代码

使用 css-loader 载入 Style 至 JavaScript 中

npm install css-loader -D
复制代码
// ./demos/css-loader/webpack.config.js
module.exports = {
  mode: "none",
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          {
            loader: "css-loader",
          },
          {
            loader: "postcss-loader",
          },
        ],
      },
    ],
  },
};
复制代码

使用 style-loader 载入 CSS 内容至 Document 中

css-loader 只负责解析并载入 .css 内容,并不负责将其载入至 Document 中。 藉由 style-loader 的帮助,可以帮我们嵌入 .css 内容至 Document 中:

npm install style-loader -D
复制代码
// ./demos/style-loader/webpack.config.js
module.exports = {
  mode: "none",
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          {
            loader: "style-loader",
          },
          {
            loader: "css-loader",
          },
          {
            loader: "postcss-loader",
          },
        ],
      },
    ],
  },
};
复制代码

### 使用mini-css-extract-plugin将 CSS 拆分至独立档案

在开发环境时,如果样式有问题时,嵌入的 Style 会难以除错,这时如果可以保持独立的 .css 档的状况下,每个 .js 个别引入了哪些样式也可以识别,对于除错是很好的帮助。这时可以借助 mini-css-extract-plugin 的帮助,让我们可以将 css 独立出来成为单一档案由 HTML 引入。

npm install mini-css-extract-plugin -D
复制代码
-plugin");

module.exports = {
  mode: "none",
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
          },
          {
            loader: "css-loader",
          },
          {
            loader: "postcss-loader",
          },
        ],
      },
    ],
  },
  plugins: [new HtmlWebpackPlugin(), new MiniCssExtractPlugin()],
};
复制代码

这里有几点要注意:

  • 不需要使用style-loader,因此从中删去
  • 加入 mini-css-extract-plugin 的 loader 以处理 CSS
  • 加入 mini-css-extract-plugin 产生独立的 style 档案
  • 加入 html-webpack-plugin 自动引入 .js.css 档案
命令行一键下载:
npm install postcss-loader css-loader mini-css-extract-plugin html-webpack-plugin -D
复制代码

webpack载入图片资源

使用file-loader路径载入

npm install -D file-loader
复制代码
// ./demos/load-image-by-path/webpack.config.js
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
  mode: "none",
  module: {
    rules: [
      {
        test: /\.png$/,
        loader: "file-loader",
      },
    ],
  },
  plugins: [new HtmlWebpackPlugin()],
};
复制代码

使用 Data URL 载入图片

图片使用路径载入时会需要多一次的请求以取得资源,这对于大图片来说是可以接受的,但对于 icon 之类的小图示,花费多次请求是浪费资源的,数量一多,会造成效能降低。

为了避免多次请求的问题,我们可以将图片转为 Data URL 直接写在引用的位置中,如此一来就不需要再次请求了,为此我们需要引入url-loader

npm install url-loader -D
复制代码
// ./demos/load-image-by-url/webpack.config.js
module.exports = {
  mode: "none",
  module: {
    rules: [
      {
        test: /\.png$/,
        use: [
          {
            loader: "url-loader",
          },
        ],
      },
    ],
  },
};
复制代码

适时切换路径与 Data URL 载入的方式

前面有提到大图片还是比较合适使用路径的引入方式,那如果我们想要依照图片的大小改变引入的方式要怎么做呢?为解决此问题,url-loader让我们可以用档案大小决定要使用的 Loaders ,我们可以设定 url-loader 选项中的limit,当档案大小超过这个数值时,预设会使用 file-loader 做处理:

// ./demos/load-image-by-url/webpack.config.js
module.exports = {
  mode: "none",
  module: {
    rules: [
      {
        test: /\.png$/,
        use: [
          {
            loader: "url-loader",
            options: {
              limit: 10240,
            },
          },
        ],
      },
    ],
  },
};
复制代码

limit的单位是 bytes ,上面的设定在 10 KB 以上的图片会由 file-loader 做处理。

读者可以变化 limit 的大小观察同张图片不同的输出情形,以了解不同载入方式的变化。

使用 svg-inline-loader可以帮助我们在 HTML 中嵌入 SVG

SVG 格式的档案与一般图片不同,它们可以被视为合法的 HTML tag ,因此我们可以直接将其内容嵌入 HTML 中。

npm install svg-inline-loader -D
复制代码
// ./demos/load-svg/webpack.config.js
module.exports = {
  mode: "none",
  module: {
    rules: [
      {
        test: /\.svg$/,
        use: [
          {
            loader: "svg-inline-loader",
          },
        ],
      },
    ],
  },
};

因为建置出来的模组会变为 HTML 代码,因此要修改嵌入方式:

// ./demos/load-svg/src/index.js
import WebpackLogo from "./webpack-logo.svg";

document.body.innerHTML = WebpackLogo;
复制代码

直接将 SVG 的内容使用 innerHTML 填进 body 中就可以了。

Loader 使用时机
file-loader 引入的图片大小较大时
url-loader 引入的图片大小较小时,像是 Icon 等小图示
svg-inline-loader 载入的图片为 SVG 格式时

一键下载

npm install file-loader url-loader svg-inline-loader -D
复制代码
小声说

点赞是不要钱的,但作者会开心好几天~

下期讲生产环境搭建一条龙,生产环境配置是实际工作中必不可少的环节,下期见~

猜你喜欢

转载自juejin.im/post/7110949772520849445