当前位置: 首页 > Web前端 > JavaScript

style-loader,我以为我明白了,但是关于style的编译我错了

时间:2023-03-27 17:06:54 JavaScript

因为webpack编译的思想是万物皆可JS,也就是说所有web项目关联的资源文件都可以通过js关联。但是由于图片和样式不兼容js,所以有各种loader来解决它们的关联问题;说到webpack风格的编译,总有几个loader是不能错过的。比如less-loader、css-loader、style-loader,只是常用的配置:constlessLoader={test:/\.less$/,use:['style-loader',{loader:'css-loader',options:{modules:true,},},'less-loader',],}上面这个文件就是告诉webpack,遇到文件名以.less结尾的文件,先用less-loader编译,然后然后使用css-loader编译,最后使用style-loader。我曾经用这么一段js伪代码来提纲://伪代码constres=styleLoader(cssLoader(lessLoader('xxx.less')));其实这段伪代码一点都不严谨。它们都是加载器,但它们的功能却大不相同。Style-loader其实和css-loader、less-loader是有区别的。后者实际上负责模块化和语法翻译;而style-loader是一个类(还有常用的mini-css-extract-plugin),负责binder功能,就是把js中的css加载到html中,让样式生效;比较随意严谨的伪代码应该这样写:constcssContent=cssLoader(lessLoader('xxx.less'));//通过styleTag将css字符串插入headstyleLoader(cssContent,document.head);写到这里看似文章应该结束了,其实乐趣才刚刚开始。之前一直以为是style-loader在构建的时候就把style插入到了html中,但其实我错了,这个错误持续了五年(你以为只是你的无知:给自己),正确的答案是将css内置到js文件中,然后在加载js文件时,通过style-loader提供的方法加载到html中。简单的说,我以前一直以为这个loader是buildtime,其实是runtime。如何判断很简单,就像判断一个网站是否是服务器端渲染一样,查看网站首页请求的html文件是否包含样式(也可以直接通过源码面板查看html文件,不元素)。造成这个误判的原因是我直接翻译了mini-css-extract-plugin的构建思路。本插件将JS中的样式剥离出来形成一个新的文件,然后将样式地址插入到html头中,这就是一个完整的构建时间。而最近为什么突然关注到这一点,是因为我们在调整一个微组件的方案。当组件加载成功后,我们发现样式丢失了。看下面这张惨不忍睹的图:经过调试,我们发现样式确实被打包到了文件中。只是它没有加载到样式标签中。第一个直觉是缺少加载器。然后查看构建工具,发现style编译配置只到css-loader级别,少了style-loader。从构建结果来看,如果样式加载过程被这篇文章结束了,似乎太不像我了。毕竟,我才是真正的我。下面我们通过一段示例代码来看看webpack的构建。如何实现样式加载。示例代码://style.lesscode@font-size:28px;.Demo{box-sizing:border-box;:global{.demo-title{字体大小:@font-size;}}}importReactfrom'react';//importstyleimportstylefrom'./style.less';exportdefaultfunctionDemo(){return(thisisademo

);}然后通过webpack使用style-loader构建。为了阅读方便,代码没有压缩和丑化。然后从入口可以看到样式导入是这样的://注释无用代码已删除__webpack_require__.d(__webpack_exports__,"default",function(){returnDemo;});varreact__WEBPACK_IMPORTED_MODULE_0__=__webpack_require__(/*!react*/"react");varreact__WEBPACK_IMPORTED_MODULE_0___default=/*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);//引入样式var_style_less__WEBPACK_IMPORTED_MODULE_1__=__webpack_require__("./src/demo/style.less");var_style_less__WEBPACK_IMPORTED_MODULE_1___default=/*#__PURE__*/__webpack_require__.n(_style_less__WEBPACK_IMPORTED_MODULE_1__);functionDemo(){return/*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__default.a.createElement("div",{className:_style_less__WEBPACK_IMPORTED_MODULE_1___defaultURE.a.Demo},/*#__P*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("h3",{className:"emo-title"},"thisisademo"));}可以看到,在入口文件中,有一个来自th的样式e./src/demo/style.lessmodule引入并赋值给_style_less__WEBPACK_IMPORTED_MODULE_1__default变量;然后顺藤摸瓜,继续看下去style.less模块??长什么样://"./src/demo/style.less"模块function(module,exports,__webpack_require__){varapi=__webpack_require__("../../../../.def/def_modules/.builders/@ali/builder-cook/node_modules/_style-loader@1.3.0@style-loader/dist/runtime/injectStylesIntoStyleTag.js");varcontent=__webpack_require__("../../../../.def/def_modules/.builders/@ali/builder-cook/node_modules/_css-loader@1.0.1@css-loader/index.js?!../../../../.def/def_modules/.builders/@ali/builder-cook/node_modules/_postcss-loader@3.0.0@postcss-loader/src/index.js?!../../../../.def/def_modules/.builders/@ali/builder-cook/node_modules/_less-loader@6.2.0@less-loader/dist/cjs.js?!./src/demo/style.less");内容=内容.__esModule?content.default:内容;if(typeofcontent==='string'){content=[[module.i,content,'']];}变量选项={};options.insert="head";options.singleton=false;varupdate=api(内容,选项);module.exports=内容nt.当地人||{};}从这块的代码可以看出,这个模块是一个连接(css导入)连接(插入html);connection是通过从less-loader/dist/cjs.js模块?!./src/demo/style.less导入的,html的插入是通过从injectStylesIntoStyleTag导入一个方法。从方法名我们可以知道它的作用是通过style标签插入css样式。还有一点就是最后的导出。该模块最终导出content.locals。继续顺着线索看是什么内容:ali/builder-cook/node_modules/_css-loader@1.0.1@css-loader/lib/css-base.js")(false);出口。push([module.i,"._1rfoVjSya7b-iuQB2_qKPh{\n-webkit-box-sizing:border-box;\nbox-sizing:border-box;\n}\n._1rfoVjSya7b-iuQB2_qKPh.demo-title{\n字体大小:28px;\n}\n",""]);exports.locals={"Demo":"_1rfoVjSya7b-iuQB2_qKPh"};}通过上面的代码可以看出export.locals的作用是css的模块化。至此,真相大白....写到最后,我似乎很享受这种前端(若智)侦探的感觉,之前为我打开了一个黑匣子,最后是那个在一句话,前端真的没什么黑魔法。基本就是红皮书上的知识。只要你能静下心来仔细看看:魔法毕竟只是一个很好的主意。