이 글은 webpack과 SPA실습에서 CSS와 기타 리소스를 관리하는 방법을 주로 소개하고 있는데, 에디터가 꽤 괜찮다고 생각해서 지금부터 공유하고 참고용으로 올려보겠습니다. 에디터를 따라가 보겠습니다
이전 글에서는 webpack을 사용하여 로컬 서비스, 자동 새로 고침, 모듈 핫 교체를 지원하는 안정적인 개발 환경을 구축하는 방법과 ES6를 사용하여 JavaScript를 작성하는 방법을 주로 소개했습니다. HTML 애플리케이션 세 가지 요소 중 또 다른 요소 – CSS 및 이미지, 글꼴 파일, 데이터 구성 파일과 같은 기타 리소스.
서문
webpack 사용법을 배울 때 webpack이 어떻게 설계되었는지, 작동 원리와 프로세스가 무엇인지에 관계없이 웹팩이 다루는 가장 기본적인 것은 HTML 태그, JavaScript, CSS, 이미지라는 점을 이해해야 합니다. , 등을 포함하며 최종 처리 결과는 DOM, JavaScript, CSS를 포함한 HTML 문서여야 합니다. CSS가 문서에 존재할 수 있는 방법에는 인라인 스타일, 인라인 스타일 및 세 가지가 있습니다. 외부 링크 스타일의 사용은 오랫동안 권장되었으므로 웹팩에서 CSS를 처리하는 방법에는 두 가지가 있습니다.
인라인 스타일: c9ccee2e6ea535a969eb3f532ad9fe89 태그를 사용하여 HTML 문서에 스타일을 삽입합니다. 외부 링크 스타일: 54221f165301041700dfeb0f4ab9fd7c 태그를 통해 CSS 파일을 생성하고 스타일을 도입합니다.
webpack은 JavaScript만 처리할 수 있으며 다른 리소스의 경우 로더와 플러그를 사용해야 합니다. -ins는 이를 JavaScript 모듈로 처리한 다음 종속성 관리를 모듈화합니다. Webpack은 모듈식 CSS를 지원하기 위해 스타일 로더와 CSS 로더라는 두 가지 로더를 제공하므로 다른 모듈에 직접 도입할 수 있습니다.
Installationnpm install --save-dev style-loader css-loader
Configuration
웹팩 구성 파일의 모듈 로더 옵션에 다음 구성을 추가하세요.
module: {
loaders: [
{ test: /\.css$/, loader: "style-loader!css-loader" }
]
}
물론, 참조 경로를 쉽게 사용하기 위해 경로를 구성할 수도 있습니다. 조각 별명:
alias: { styles: path.resolve(__dirname, 'src/styles/') }
이때 import 'styles/index.css';
는 import '../src/styles/indx와 같은 상대 경로를 사용하는 것과 동일합니다. css';
import 'styles/index.css';
等同于使用相对路径,如import '../src/styles/indx.css';
使用
配置好以后,假如我们在styles目录下创建了一个index.css文件,现在可以在JavaScript文件中直接引入该CSS: import 'styles/index.css'; 或 require('styles/index.css');
css内容如下:
html, body { width: 100%; height: 100%; } .container { color: red; }
页面展示如图:
内联样式
前面提到了webpack处理CSS的方式有两种,第一种是以内联方式在页面93f0f5c25f18dab9d176bd4f6de5d30e标签内动态插入c9ccee2e6ea535a969eb3f532ad9fe89内联样式,这种方式也是webpack的默认处理方式,只需要简单配置如下加载器:
{ test: /\.css$/, exclude: /node_modules/, loader: 'style-loader!css-loader' // or // loaders: ['style-loader', 'css-loader'] }
WEBPACK加载器解析顺序
如上面代码所示,无论是字符串语法style-loader!css-loader
,亦或是数组语法['style-loader', 'css-loader']
css 내용은 다음과 같습니다:
npm install --save-dev extract-text-webpack-plugin페이지는 그림과 같이 표시됩니다:
인라인 스타일
앞서 언급했듯이 두 가지 방법이 있습니다. webpack은 CSS를 처리합니다. 첫 번째는 페이지93f0f5c25f18dab9d176bd4f6de5d30e 태그 내에 c9ccee2e6ea535a969eb3f532ad9fe89 인라인 스타일을 삽입하는 것입니다. 이 방법은 webpack의 기본 처리 방법이기도 합니다.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' }) ]
style-loader!css-loader
인지 배열 구문 ['style-loader', ' css-loader']
, webpack 구문 분석 규칙은 오른쪽에서 왼쪽으로, 로더 처리 파일이 순차적으로 구문 분석되어 실행됩니다. 이전 로더 처리의 출력은 최종 로더 처리까지 다음 로더 처리의 입력입니다. 여기에서 완료되면 webpack은 먼저 css-loader 로더를 호출하여 css 파일을 처리한 다음 처리 결과를 스타일 로더 로더에 전달하고 스타일 로더는 입력을 수락하고 계속 처리합니다. CSS-LOADER
css-loader 로더의 기능은 require('./index.css')와 같은 JavaScript 모듈을 사용하는 것처럼 JavaScript 파일에서 CSS 파일을 참조할 수 있도록 지원하는 것이므로 해당 기능을 CSS 파일을 변환하는 것으로 생각할 수 있습니다. JavaScript 모듈에 포함되어 있으므로 JavaScript 모듈을 도입하여 직접 참조할 수 있습니다.
Parameters
css-loader에는 일반적으로 사용되는 두 가지 매개변수가 있습니다.
🎜🎜🎜modules: {boolean}은 CSS 모듈을 사용할지 여부를 지정합니다(예: 로컬 또는 글로벌 스타일 규칙을 설정하기 위한 로컬 및 글로벌). 기본값은 false인 경우 css-loader?modules;🎜🎜🎜🎜importLoaders와 같은 설정을 엽니다. {number}는 css-loader 로더 이전에 사용되는 로더 수를 지정합니다. 기본값은 0입니다. css-loader?importLoaders=1과 같은 설정입니다. ;🎜🎜🎜🎜🎜STYLE -LOADER🎜🎜🎜웹팩이 CSS 파일을 어떻게 처리하든, 실제로 CSS 규칙을 사용하려면 CSS 파일을 페이지에 출력해야 합니다. 스타일 로더 로더는 CSS를 인라인으로 삽입합니다. 즉, 각 입력(require를 통해 도입되고 css-loader를 사용하여 JavaScript 모듈로 변환되고 입력으로 style-loader에 전달됨)에 대해 style-loader는 93f0f5c25f18dab9d176bd4f6de5d30e 페이지의 태그와 태그의 스타일 규칙은 다음 입력 콘텐츠입니다. 예: 🎜🎜🎜🎜外链样式
当然,我们并不总是希望所有样式都以内联方式存在页面中,很多时候我们也希望通过外链方式使用样式表,特别是样式规则较多的时候,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,图片,字体等资源文件;组件的迁移公用成本很低。不过组件化开发并不是说不需要资源目录了,一些公用的资源依然放在项目的基础目录下。
说明
웹팩을 활용한 CSS, 이미지, 폰트, 데이터 리소스 관리 실무에 대한 기본 요약을 드디어 완성했습니다. 사실 아직 소개할 내용이 많이 남아있는 것 같지만 꼭 짚고 넘어가야 할 내용입니다. 글의 내용이 명쾌하고 문장이 매끄럽게 되도록 노력하고, 길이가 너무 길거나 평탄하지 않도록 노력하세요. 이 시리즈에서는 webpack을 사용하여 SPA 애플리케이션을 개발하는 방법에 대해 보다 완전하고 명확한 설명을 제공하기 위해 노력하고 있습니다.
위 내용은 제가 여러분을 위해 정리한 내용입니다. 앞으로 도움이 되길 바랍니다.
관련 기사:
gulp를 사용하여 전체 프로젝트 프로세스를 만드는 방법
jQuery에서 페이지 요소를 동적으로 제어하는 방법
위 내용은 webpack 및 SPA에서 CSS 및 기타 리소스를 관리하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!