Home >Web Front-end >JS Tutorial >How to manage CSS and other resources in webpack and SPA
This article mainly introduces the methods of managing CSS and other resources in webpack and SPA practice. The editor thinks it is quite good, so I will share it with you now and give it as a reference. Let’s follow the editor and take a look.
The previous article introduced how to use webpack to build a stable development environment that supports local services, automatic refresh, module hot replacement, and writing JavaScript using ES6. This article mainly introduces webpack. How to handle another element of the three major elements of HTML applications - CSS and other resources such as images, font files or data configuration files.
Preface
When learning to use webpack, we need to understand that no matter how it is designed, what its working principle and process are, the most fundamental thing it processes is HTML. HTML tags, JavaScript, CSS, images and other resources in the document, and the final processing result must still be an HTML document, including DOM, JavaScript, CSS. There are three ways for CSS to exist in the document: inline style, inline The use of styles, external link styles, and inline styles has long been deprecated, so there are only two ways for webpack to process CSS:
webpack With CSS
, we know that webpack can only process JavaScript. For other resources, loaders and plug-ins need to be used to process them into JavaScript modules, and then perform module dependency management. Webpack provides two loaders, style-loader and css-loader, to support our modular CSS, so it can be introduced directly in other modules.Installation
npm install --save-dev style-loader css-loader
Configuration
Add the following configuration in the module loader option of the webpack configuration file:
module: { loaders: [ { test: /\.css$/, loader: "style-loader!css-loader" } ] }Of course, in order to facilitate the use of reference paths, you can also configure path fragment aliases:
alias: { styles: path.resolve(__dirname, 'src/styles/') }At this time,
import 'styles/index.css'; is equivalent to using a relative path, such as
import '../src/styles/indx.css';
Use
After configuring, if we create it in the styles directory An index.css file has been created, and now the CSS can be introduced directly into the JavaScript file: import 'styles/index.css'; or require('styles/index.css');The css content is as follows:html, body { width: 100%; height: 100%; } .container { color: red; }The page is displayed as shown in the figure:
Inline style
As mentioned earlier, the way webpack handles CSS is There are two types. The first one is to dynamically insert the c9ccee2e6ea535a969eb3f532ad9fe89 inline style in the 93f0f5c25f18dab9d176bd4f6de5d30e tag of the page. This method is also the default processing method of webpack. You only need to simply configure the following loader:{ test: /\.css$/, exclude: /node_modules/, loader: 'style-loader!css-loader' // or // loaders: ['style-loader', 'css-loader'] }
WEBPACK loader parsing order
As shown in the above code, whether it is string syntaxstyle-loader!css-loader, or array syntax
['style-loader', 'css-loader'] , webpack parsing rules are from right to left, parsing and executing loader processing files in sequence, the output of the previous loader processing is the next load The input processed by the loader until the final loader processing is completed; here, webpack first calls the css-loader loader to process the css file, and then passes the processing result to the style-loader loader, and the style-loader accepts the input and continues processing.
CSS-LOADER
We have repeatedly emphasized that webpack can only process JavaScript, so for other resources such as css or images, you need to use a loader to convert and output them to JavaScript module, webpack can continue processing. The function of the css-loader loader is to support us in referencing CSS files in JavaScript files like using JavaScript modules, such as require ('./index.css'), so you can think of its function as The file is converted into a JavaScript module, so we can directly reference it by introducing the JavaScript module.Parameters
css-loader has two common parameters:STYLE-LOADER
No matter How webpack processes CSS files, they ultimately need to be output to the page before the CSS rules can actually be used. The style-loader loader inserts CSS into the page document inline, that is: for each input (introduced through require, use css-loader converts it into a JavaScript module and passes it to style-loader as input), style-loader inserts a c9ccee2e6ea535a969eb3f532ad9fe89 tag in the page's 93f0f5c25f18dab9d176bd4f6de5d30e tag, and the style rules in the tag are the input content, as shown in the following example:外链样式
当然,我们并不总是希望所有样式都以内联方式存在页面中,很多时候我们也希望通过外链方式使用样式表,特别是样式规则较多的时候,webpack开发者们当然考虑了这样的需求。
webpack提供的style-loader
加载器默认是以内联方式将样式插入文档,我们需要使用webpack extract-text-webpack-plugin
插件以实现输出单独CSS文件。
EXTRACT TEXT PLUGIN
安装
首先安装该插件:
npm install --save-dev extract-text-webpack-plugin
配置
然后添加如下配置:
var ExtractTextPlugin = require('extract-text-webpack-plugin'); ... module: { loaders: [ { test: /\.css$/, exclude: /node_modules/, // 老版本 loader: ExtractTextPlugin.extract('style-loader', 'css-loader') loader: ExtractTextPlugin.extract({ fallback:'style-loader', use: 'css-loader' }) } ] }, plugins: [ // 生成独立css文件 new ExtractTextPlugin({ filename: 'css/[name].css' }) ]
运行webpack命令,我们会看到在dist/css/文件夹下生成相应的CSS文件。
参数
filename {String | Function}
Extract Text Plugin为每个入口生成一个CSS文件,所以对于多入口项目需要指定filename参数[name]或[id]或[contenthash]生成唯一识别文件名;
disable {Boolean}
禁用此插件;
allChunks {Boolean}
allChunks: true;时指定从所有模块中抽取CSS输出至单独CSS文件,包括异步引入的额外模块;此插件默认是只抽取初始模块内引入的CSS;
extract方法
该方法可以以参数指定加载器,然后接受该加载器的输出,进行处理。需要在加载器和插件配置中同时声明相关配置,才能实现效果;在加载器配置中调用其extract方法传入通常以下两个参数:
1. use: 将CSS转换成模块的加载器;
2. fallback: 对于不被抽取输出至单独CSS文件的CSS模块使用的加载器,上例中`style-loader`即说明以内联方式使用,该加载器通常在`allChunks: false`时处理额外的模块;
FILENAME与OUTPUT
在上一篇介绍了输出文件配置output相关内容,其中:
output.path是webpack处理文件后输出的路径,对于CSS文件输出依然适用,即CSS文件也将输出至该目录;
output.publicPath是指浏览器访问资源时的相对基础路径,规则是: output.publicPath + output.filename;
你可以看到在本系列文章实例中filename都添加了前缀目录,如css和scripts,你可能看到很多项目是不添加的,但文件入口较多时建议分类型目录输出,而且需要记得在浏览器访问资源时也需要添加该目录层级。
CSS预处理器
通常在开发较复杂的应用时,我们都会选择一种CSS的强化辅助工具,以更高效,更方便的使用CSS开发应用样式,这些拓展工具就是所说的CSS预处理器.
CSS预处理器(preprocessors)在CSS语法的基础上增加了变量 (variables)、嵌套 (nested rules)、混合 (mixins)、导入 (inline imports) 等高级功能,令CSS更加强大与优雅,有助于更好地组织管理样式文件,以及更高效地开发项目。
目前最常见的CSS预处理器有LESS,SASS,Stylus,个人用过的是前两种,使用SASS的还是居多。
SASS
安装
npm install --save-dev sass-loader
安装sass-loader以后会发现,package.json中多了一个node-sass依赖,这是使用SASS必须的。
配置
然后添加以下配置:
{ test: /\.s[ac]ss$/, exclude: /node_modules/, loader: 'style-loader!css-loader!sass-loader' }
如上,配置中传递了三个加载器,相对于前文处理CSS文件的加载器,在最后面多了一个sass-loader,首先加载sass-loader加载器处理SASS文件成CSS代码,然后继续按照前文描述流程处理CSS文件。
EXTRACT TEXT PLUGIN
和处理CSS文件一样,上述配置最终通过style-loader将转换后的CSS代码内联到页面,我们需要使用Extract Text Plugin生成单独CSS文件,以外链方式引用:
{ test: /\.s[ac]ss$/, exclude: /node_modules/, loader: ExtractTextPlugin.extract({ fallback:'style-loader', use: [ 'css-loader', 'sass-loader' ] }) } ... // 生成独立css文件 new ExtractTextPlugin({ filename: 'css/[name].css' })
CSS后处理器
前面讲到CSS预处理器,如SASS,他们提供对CSS的拓展,包括语法拓展,高级特性拓展,如嵌套,变量,自动处理添加属性前缀等,使得我们可以以其定义的语法与模板方式更高效的编写CSS,然而这些预处理器都是另外对CSS进行拓展,各自定义了语法和模板,其处理流程是对代码进行解析处理,然后转换成CSS代码。
不同预处理器有各自的定义和规范,假如你需要从LESS转到SASS,源代码转换成本和学习成本颇高,而接下来要介绍的CSS后处理器并没有这个问题。
不同于预处理器预定义好一个语法和模板,然后对按照该语法和模板编写的代码进行处理转换成CSS,其输入是自定义语法文件,输出是CSS代码;后处理器(postprocessor)是对原生CSS代码根据配置进行处理,其输入输出依然是CSS代码。
POSTCSS
现在最受欢迎的CSS后处理器,就是postcss:
PostCSS is a tool for transforming styles with JS plugins. These plugins can lint your CSS, support variables and mixins, transpile future CSS syntax, inline images, and more.
PostCSS是一个使用Js插件转换样式的根据,插件支持拓展CSS,如变量,混合,CSS属性语法兼容,行内图片等等功能。
特性
不同于SASS提供一个功能性拓展工具,postcss更多的是提供一个CSS高效开发工具解决方式,其本身只包含CSS解析器只能将CSS处理成一棵抽象语法树(AST),同时提供一个丰富的CSS节点树API,可以对语法树进行操作,另外它有一个高拓展性的插件系统支持我们通过引入不同插件对CSS进行处理,一个插件的输出还可以是下一个插件的输入,更值得一提的是,这些插件都是JavaScript插件,前端开发者们很容易就能根据项目需求定制自己的插件,所以可以总结几点一以下特性:
postcss只处理CSS,概念简洁;
提供高拓展性的插件系统支持按需引入不同插件,实现不同处理;
使用JavaScript插件,开发者可以很方便定制项目插件;
提供CSS节点树API,可以高效的进行CSS处理;
安装
在webpack中使用,需要先安装对应加载器:
npm install --save-dev postcss-loader
插件
postcss目前有200+插件,足够满足绝大部分项目开发需求,可以查看postcss插件,我们介绍几个主要使用的插件。
Autoprefixer
回顾一下在预处理器中,如果我们需要为CSS代码添加属性前缀,需要这么实现呢?对于Sass,我们通常使用mixin,即混合宏,处理CSS属性前缀,如:
// 定义 @mixin prefix-animation($animation-name){ animation:$animation-name; -webkit-animation:$animation-name; } // 使用 body{ @include prefix-animation(loading .5s linear infinite); }
如上,我们需要按照定义的语法和模板:先定义一个mixin,然后通过@include方式使用,最后才能输出添加前缀的CSS代码,当代码越来越多时,我们需要定义的mixin也会越来越多,而且不同预处理器定义的语法和模板都有差异,学习成本、转换成本都很可能令人难以接受。
那么postcss插件怎么处理的呢?postcss提供了Autoprefixer插件处理CSS属性前缀:
Autoprefixer插件基于Can I Use的数据,对CSS规则进行前缀处理。
安装
首先还是要安装Autoprefixer:
npm install --save-dev autoprefixer
配置
添加如下配置:
module: { loaders: [ { test: /\.css$/, exclude: /node_modules/, loaders: [ 'style-loader', 'css-loader', { loader: 'postcss-loader', options: { plugins: [ require('autoprefixer')({ browsers: ['last 2 versions'] }) ] } } ] } ] }
如上,我们知道postcss是一个样式开发解决方案,其特定功能需要引入插件实现,上例中在指定postcss-loader加载器时为其设置了插件配置autoprefixer;当然webpack还支持直接设置一个postcss配置文件,然后在项目根目录创建postcss.config.js配置文件,内容格式如下:
module.exports = { plugins: [ require('autoprefixer')({ browsers: ['last 2 versions'] }) // or just require('autoprefixer') ] }
使用autoprefixer插件时可选传入browsers参数,可以设置添加前缀的适配范围,详细可查阅browsers配置说明。
混合使用CSS预处理器与后处理器 – PreCSS
也许你迫不及待想在项目中引入postcss,又希望能继续使用CSS预处理器语法,而且需要保证以前按照某预处理器预定语法和模板(如SASS)编写的源代码继续稳定使用,不需要太多的迁移和学习成本,可以做到吗?当然可以,可以使用预处理器PreCSS插件包,另外我们需要安装一个postcss的scss解析器,因为postcss默认只包含一个CSS解析器,postcss配置文件更新如下:
module.exports = { parser: require('postcss-scss'), plugins: [ require('autoprefixer')({ browsers: ['last 2 versions'] }), require('precss') ] }
webpack配置文件更新配置:
modules: { loaders: [ { test: /\.s?[ac]ss$/, exclude: /node_modules/, // or 内联方式 loader: 'style-loader!css-loader!postcss-loader' loader: ExtractTextPlugin.extract({ fallback:'style-loader', use: [ 'css-loader', 'postcss-loader' ] }) } ] }
可以看到文件匹配规则,修改为/\.s?[ac]ss$/,可以匹配包括.sass, .scss, .css样式文件;在css-loader加载器之前添加了postcss-loader加载器(webpack加载器解析顺序为从右至左)。
当然你可以不使用precss,依然使用sass-loader,则只需要修改配置:
loader: 'style-loader!css-loader!postcss-loader!sass-loader'
对于如下SCSS代码:
$column: 200px; .menu { display: flex; width: calc(4 * $column); }
转换生成如下CSS代码:
.menu { display: -webkit-box; display: -ms-flexbox; display: flex; width: calc(4 * 200px); }
处理图片与字体文件
对于一个应用而言,除了需要开发HTML、CSS、JavaScript,通常还好使用到图片,字体文件,配置文件等诸多资源,那么前端工程化流程也就必然需要对这些资源进行处理与优化,最典型的说处理图片和字体文件。
在Grunt或Gulp中,我们对图片和字体文件的处理通常是将其从源目录压缩优化处理后输出至输出目录,通常是以文件目录整体进行处理,每次构建时,对所有资源,包括未使用的图片均进行处理,效率是有局限的;而webpack中一切资源文件都可以处理成模块,然后在编译时管理模块依赖,可以做到只处理存在依赖的资源(即,使用了的资源)。
图片与字体
当我们在Js模块中引入CSS文件时,其中样式规则中的背景图片,字体文件如何处理呢?webpack只能管理模块化的东西,需要将其模块化,然后使用webpack管理依赖,webpack提供了file-loader加载器:
File Loader
Instructs webpack to emit the required object as file and to return its public url.
通知webpack将引入的对象输出为文件并返回其公开资源路径。
配置
module: { loaders: [ { test: /\.(png|svg|jpe?g|gif)$/, loader: [ 'file-loader' ] } ] }
说明
当我们在js文件中import Image from '../images/test.png'或在CSS文件中url('../images/test.png')时,file-loader将处理该图片并在output.path目录下输出文件,然后将../images/test.png路径替换成该输出文件路径。
注,对于html中引用的图片,需要使用[html-loader]加载器处理(http://npm.taobao.org/package/html-loader)。
参数
emitFile: 是否输出文件;
name: 指定输出文件的文件名,有几个可用内置变量:
[name]: 引用资源的名称;
[path]: 引用资源的相对路径;
[ext]: 资源拓展名;
[hash]: 资源内容的hash值,默认使用md5算法计算得到,可以指定长度值,如[hash:7]表示返回hash值前7个字符;
[hashType:hash:digestType:length]: 指定hash值计算算法类型和摘要类型,及摘要长度,如sha512:hash:base64:7表示使用sha512加密算法计算hash值并且返回7个字符的base64编码字符
实例
在配置时可以指定参数:file-loader?name=[name].[ext]?[hash:8]
或者以配置对象方式:
{ test: /\.(png|svg|jpe?g|gif)$/, loaders: [ // 'file-loader?name=[path][name].[ext]?[hash:8]' { loader: 'file-loader', query: { name: '[path][name].[ext]?[hash:8]' } } ] }
对于CSS源代码:
.wrapper { font-size: 18px; background: url('../images/test.png') no-repeat 0 0; }
输出CSS代码如下:
.wrapper { font-size: 18px; background: url(assets/images/test.png?59427321) no-repeat 0 0; }
assets为output.publicPath指定值,images/test.png?59427321为配置文件中指定的name模板,在output.path目录下输出images/test.png,区别是,不会携带?后的参数。
另外,你也可以在js模板中这样使用:
<img src={imgSrc} /> ... import imgSrc from 'path/xxx.png';
Url Loader
你可能会发现前面并没有安装file-loader,因为有更好用的加载器url-loader,url-loader加载器是file-loader的升级版,他们唯一的不同之处在于:
url-loader可以通过limit参数指定一个尺寸值,加载器会对小于该值的资源处理返回一个Data URL,以base64的方式嵌入HTML或CSS,如url-loader?limit=65000;对于大于该尺寸的资源将使用file-loader处理并且传递所有参数。
mimetype
还可以设置mimetype对处理文件进行过滤,如url-loader?mimetype=image/png将只处理png类型的资源。
安装
npm install --save-dev url-loader
配置
该加载器对于图片和字体文件资源都适用:
{ test: /\.(png|svg|jpe?g|gif)$/, loaders: [ // 'url-loader?name=[path][name].[ext]?[hash:8]' { loader: 'url-loader', query: { limit: 6000, name: '[path][name].[ext]?[hash:8]' } } ] }, { test: /\.(woff|woff2|eot|ttf|otf)$/, loaders: [{ loader: 'url-loader', query: { limit: 10000, name: '[path][name].[ext]?[hash:8]' } }] }
资源优化
完成以上配置后,已经可以在项目中很方便的引用各自资源了,但是通常我们还需要对图片字体等文件进行压缩优化处理,如Grunt中使用的imagemin插件一样压缩资源,webpack则提供了相关加载器img-loader。
安装
npm install --save-dev img-loader
配置
{ test: /\.(jpe?g|png|gif|svg)$/i, loaders: [ 'url-loader?name=[path][name].[ext]?[hash:8]', { loader: 'img-loader', options: { // 根据环境判断是否启用资源压缩 enabled: process.env.NODE_ENV === 'production', gifsicle: { interlaced: false // 替换使用渐进式渲染 }, mozjpeg: { progressive: true, // 创建基准jpeg文件 }, optipng: { optimizationLevel: 4, // 优化级别,0-7,值越大,压缩越多 }, pngquant: { quality: '75-90', // 压缩质量,0-100,值越高,质量越高 speed: 3 // 执行速度,0-10,速度过高质量受损,不建议过高 }, svgo: { plugins: [ { removeTitle: true }, // 去除标题信息 { convertPathData: false } // 转换路径为更短的相对或决定路径 ] } } } ] }
以上为常见使用配置,更多详细配置信息请查看对应说明imagemin文档,特别注意的是上面使用了process.env.NODE_ENV当前环境变量,只有在生产环境启用图片压缩,因为压缩过程比较比较耗时,可能会降低开发、调试效率。
数据资源
对于数据类型文件资源,webpack内置支持加载解析.json文件,而其他类型则需要安装配置相应加载器,如.xml文件,需要安装并配置xml-loader。
资源管理的思考
在传统或稍早一点的应用中,我们通常会将所有的图片,字体等资源放在一个基础目录下,如assets/或images,但是对于那些在多项目间重复的插件代码或资源来说,每一次迁移,我们都得在一大堆图片,字体资源里寻找出我们需要迁移的资源,这对代码可重用和其独立性有一定限制,而且与现在提倡的组件化开发模式也不相符。
webpack对于资源的处理方式给组件化开发提供了很大便利,使得我们以组件为单位,可以在某一组件目录下存放所有相关的js,css,图片,字体等资源文件;组件的迁移公用成本很低。不过组件化开发并不是说不需要资源目录了,一些公用的资源依然放在项目的基础目录下。
说明
I can finally breathe a sigh of relief. I have completed a basic summary of the practice of managing CSS, images, fonts, and data resources with webpack. In fact, I feel that there is still a lot to introduce, but we must try to ensure that the article has clear ideas, smooth sentences, and the length cannot be too long. , the level is limited, and it takes a lot of time to experience, I hope it can be helpful to readers, and subsequent chapters will continue to be interspersed with introductions, striving to give this series a more complete and clear description of how to use webpack to develop SPA applications.
The above is what I compiled for everyone. I hope it will be helpful to everyone in the future.
Related articles:
Using axios to upload files in vue
How to add an array to an object in js
How to create a complete project process using gulp
How to dynamically control page elements in jQuery
How to implement the track playback function in canvas
The above is the detailed content of How to manage CSS and other resources in webpack and SPA. For more information, please follow other related articles on the PHP Chinese website!