webpack如何将css文件分离的,【Webpack小书】Webpack中如何将CSS样式抽取到独立文件中? - Tim的资源站...

现在我们有一个很好的打包了,但所有的 CSS 都去了哪里?根据配置,它已被内联到 JavaScript!虽然这在开发过程中很方便,但听起来并不理想。

当前的解决方案 CSS 是无法缓存的,并且还有一个未样式化元素闪动(FOUC)问题。发生 FOUC 是因为浏览器需要一段时间才能加载 JavaScript,并且到那时才会应用样式。将 CSS 分离到自己的文件可以让浏览器单独管理它,从而避免了这个问题。

Webpack 提供了一种使用 mini-css-extract-plugin(MCEP)生成单独的 CSS 包的方法。它可以将多个 CSS 文件聚合为一个。出于这个原因,它配备了一个 loader 来专门处理这个过程。然后,插件会获取 loader 抽取的结果并发出单独的文件。

由于这个过程会产生比较大的开销,所以,MiniCssExtractPlugin 只会作用于编译阶段,它不适用于热模块更换(HMR)。鉴于这个插件只是在生产环境中使用,所以也不是什么大的问题。

在生产环境中,使用内联样式可能有潜在危险,因为它向外提供了一个攻击途径。关键路径渲染借鉴了这个思路,它将关键 CSS 内联到初始 HTML 中,从而提高了站点的感知性能。在有限的上下文中,内联少量的 CSS 可能是加速初始加载(更少的请求)的可行选择。

配置 MiniCssExtractPlugin

首先安装插件:

npm install mini-css-extract-plugin --save-dev

MiniCssExtractPlugin 包括一个 MiniCssExtractPlugin.loader,用来标记要提取的资源。然后,插件基于这个标记执行资源提取的工作。

将以下配置添加到配置的开头:

webpack.parts.js

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

exports.extractCSS = ({ include, exclude, use = [] }) => {

// 将 css 抽出

const plugin = new MiniCssExtractPlugin({

filename: "[name].css",

});

return {

module: {

rules: [

{

test: /\.css$/,

include,

exclude,

use: [

MiniCssExtractPlugin.loader,

].concat(use),

},

],

},

plugins: [plugin],

};

};

该 [name] 占位符使用引用 CSS 的入口的名称。“ 添加哈希值到文件名”一章中详细讨论了占位符和散列。

如果要将结果文件输出到特定目录,可以通过传递路径来完成。例如:filename: "styles/[name].css"。

合并配置

使用以下配置将部分配置合并到主配置上:

webpack.config.js

const productionConfig = merge([

parts.extractCSS({

use: "css-loader",

}),

]);

const developmentConfig = merge([

...

parts.loadCSS(),

]);

使用此设置,您仍然可以在开发期间受益于 HMR。但是对于生产构建,可以生成单独的 CSS。HtmlWebpackPlugin 自动拾取并将其注入到 index.html。

如果您使用的是 CSS Modules,请按照“ 加载样式”一章中的说明进行相应的调整。您可以为标准 CSS 和 CSS Modules 维护单独的设置,以便通过独立的逻辑加载它们。

通过 npm run build 运行后,您应该看到类似于以下内容的输出:

Hash: 45a5e26cc963eb12db02

Version: webpack 4.1.1

Time: 752ms

Built at: 3/16/2018 4:24:40 PM

Asset Size Chunks Chunk Names

main.js 700 bytes 0 [emitted] main

main.css 33 bytes 0 [emitted] main

index.html 220 bytes [emitted]

Entrypoint main = main.js main.css

[0] ./src/index.js + 1 modules 247 bytes {0} [built]

| ./src/index.js 99 bytes [built]

| ./src/component.js 143 bytes [built]

[1] ./src/main.css 41 bytes {0} [built]

...

现在样式已被抽取到单独的 CSS 文件中。因此,JavaScript 包变得略小。你也避免了 FOUC 问题。浏览器不必等待 JavaScript 加载以获取样式信息。相反,它可以单独处理CSS,避免画面闪动。

如果您收到 Module build failed: CssSyntaxError:或Module build failed: Unknown word 的错误,请确保您的通用配置没有设置与 CSS 相关的部分。

管理 JavaScript 之外的样式

尽管通过 JavaScript 引入样式,然后再打包是推荐的做法;但我们也可以在入口通过 glob 找到 CSS 文件来达到同样的目的:

...

const glob = require("glob");

...

const commonConfig = merge([

{

entry: {

...

style: glob.sync("./src/**/*.css"),

},

...

},

...

]);

在进行此类更改后,您不必从应用程序代码中引用样式。这也意味着 CSS Modules 不再起作用,你也必须小心 CSS 规则的排序。

按照上面的配置,您应该同时获得 style.css 和 style.js。后一个文件包含类似 webpackJsonp([1,3],[function(n,c){}]); 的内容,它会像 webpack issue 1967 中所讨论的那样不做任何事情。

如果您想要严格控制排序,可以设置一个单独的 CSS 入口,然后使用 @import 语句将其余部分的样式导入到项目中。另外一种做法是设置JavaScript 入口并通过 import 语句获得相同的效果。

总结

当前的配置将样式与 JavaScript 干净地分离开来。即使该技术对 CSS 最有价值,它也可用于提取 HTML 模板或您使用的任何其他文件类型。困难的是,这与 MiniCssExtractPlugin 的设置有关,但这种复杂性可隐藏在抽象背后。

回顾一下:

使用 MiniCssExtractPlugin 样式解决了 FOUC 的问题、CSS 缓存失效问题以及潜在的攻击风险。

如果您不希望通过 JavaScript 引入样式,还可以通过入口来引入它。但是,在这种情况下,您必须小心样式规则的排序。

在下一章中,您将学习如何从项目中去除未使用的 CSS。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值