Linaria 是一个近似于 styled-components 和 emotion JSS 框架,不同点在于, styled-components 和 emotion 是一个 运行时 方案,而 Linaria 是一个 编译期 + 运行时 方案。
运行时的 JSS 方案必须内置一个 css 处理器,并且在运行时去解析,分别增加了体积和性能上的成本。 Linaria 创造性的在编译期将相应的 JSS 解析出来,抽出解压到一个 CSS 文件中,并将相应的 JSS 代码替换成一个指向某个 css 类名的字符串,避免了运行时方案的问题。
对于以下代码
import { css } from '@linaria/core'
let size = 5;
size = (function() { return 3; }());
const headerClassName = css`
text-align: center;
color: #fff;
`;
const headerTitleClassName = css`
.${headerClassName} {
font-size: ${size}px;
}
`;
console.log(headerClassName, headerTitleClassName);
Linaria 会将其编译为
// index.bundle.js
var size = 5;
size = function () {
return 3;
}();
var headerClassName = "hf71da1";
var headerTitleClassName = "hi1y09m";
console.log(headerClassName, headerTitleClassName);
/* index.css */
.hf71da1{text-align:center;color:#fff;}
.hi1y09m .hf71da1{font-size:3px;}
通过编译后的代码我们可以看出:
Linaria 的实现依赖于 wbepack(rollup) 和 babel 是必然的,使用 Linaria 必须在 webpack 和 babel 分别设置 @linaria/webpack4-loader 和 @linaria/babel 才可以。
通过 webpack 使用 Linaria 需要 .rules 上进行如下配置
{
test: /.(js|ts)$/,
use: [
'babel-loader',
'@linaria/webpack4-loader''
],
},
所有的 JS 代码都会经过 @linaria/webpack4-loader ,其核心代码如下
export default function index(
this: LoaderContext,
sourceCodes: string,
inputSourceMap: RawSourceMap | null
) {
result = transform(sourceCodes, {
filename: path.relative(process.cwd(), this.resourcePath),
inputSourceMap: inputSourceMap ?? undefined,
outputFilename,
pluginOptions: rest,
preprocessor,
});
if (result.cssText) {
let { cssText } = result;
if (sourceMap) {
cssText += `/*# sourceMappingURL=data:application/json;base64,${Buffer.from(
result.cssSourceMapText || ''
).toString('base64')}*/`;
}
if (result.dependencies?.length) {
result.dependencies.forEach((dep) => {
try {
const f = resolveSync(path.dirname(this.resourcePath), dep);
this.addDependency(f);
} catch (e) {
// eslint-disable-next-line no-console
console.warn(`[linaria] failed to add dependency for: ${dep}`, e);
}
});
}
this.callback(
null,
`${result.code}\n\nrequire(${loaderUtils.stringifyRequest(
this,
outputFilename
)});`,
result.sourceMap ?? undefined
);
return;
}
是一个标准的 webpack 异步 loader ,@linaria/webpack4-loader 做的事情就是把传入的源代码当做参数传入、调用 transform 函数,这个函数来自 @linaria/babel ,@linaria/babel 是 Linaria 维护的解析 JSS 代码的 babel-preset 。
export default function transform(code: string, options: Options): Result {
// Check if the file contains `css` or `styled` words first
// Otherwise we should skip transforming
if (!/\b(styled|css)/.test(code)) {
return {
code,
sourceMap: options.inputSourceMap,
};
}
// ...
const ast = parseSync(code, {
...babelOptions,
filename: options.filename,
caller: { name: 'linaria' },
});
const { metadata, code: transformedCode, map } = transformFromAstSync(
ast!,
code,
//.....
)!;
const {
rules,
replacements,
dependencies,
} = (metadata as babel.BabelFileMetadata & {
linaria: LinariaMetadata;
}).linaria;
const mappings: Mapping[] = [];
let cssText = '';
Object.keys(rules).forEach((selector, index) => {
mappings.push({
generated: {
line: index + 1,
column: 0,
},
original: rules[selector].start!,
name: selector,
source: '',
});
// Run each rule through stylis to support nesting
cssText += `${preprocessor(selector, rules[selector].cssText)}\n`;
});
return {
code: transformedCode || '',
cssText,
rules,
replacements,
dependencies,
sourceMap: map
};
}
transform 内部首先会判断代码是否使用 Linaria 的 api ,如果使用了则解析相应的 JSS 代码,**并执行相关的 JS 代码,**这也是为什么本文开头例子处编译后样式表的 font-size 的值为 3 而非 5 的原因。解析的时候,@linaria/babel 会将 JSS 中的 css 代码写到 metadata 里,而非转化后的源代码处,随后交付给 @linaria/webpack4-loader 处理。
metadata 是 babel 解析、转译代码时用于储存一些辅助信息的地方,其内容适用于辅助转译流程的,转译完成后就不存在了
也就是说,@linaria/babel 只负责将 JSS 代码根据文件路径计算出一个哈希名,作为类名,替换相应的JSS 代码。 css 解压相关的操作由 @linaria/webpack4-loader 负责。
@linaria/webpack4-loader 会将 metadata 里 css 解压到 .linaria-cache/index.linaria.css 里,然后在转化后的源代码末尾处加上 require("./.linaria-cache/index.linaria.css") ,随后 webpack 解析时就会将解析 .css 文件相关操作委托到处理 .css 文件的 loader ,此时我们可以自由选择使用 mini-css-extract-plugin 还是 style-loader ,或者其他的 .css loader ,重点在于我们拥有了 webpack 和 .css 文件相关的生态,而其他的 JSS 方案就没法做到这点。
越来越多的人开始站队 Angular、Vue、React,仅仅围绕这些库或者框架进行前端技术讨论,这实在不是什么好的现象。其实我想基于我个人的经验聊下前端的演进和未来,希望可以贡献微薄的力量,消除一些我个人认为的前端社区不太好的风气。
近几年可谓是 JavaScript 的大爆炸纪元,各种框架类库层出不穷,它们给前端带来一个又一个的新思想。从以前我们用的 jQuery 直接操作 DOM,到 BackboneJS、Dojo 提供监听器的形式,在到 Ember.js、AngularJS 数据绑定的理念,再到现在的 React、Vue 虚拟 DOM 的思想。
新框架(新工具,语言),一、了解概念,把握思路,二、迅速实战,见招拆招,三、深入文档,求人不如求己,四、掌握原理,有恃无恐,五、源码分析,自立门户。如果你已经熟悉一门计算机语言,当再学习其他语言的时候,会发现他们几乎是大同小异,对比着学习,会令你事半功倍。
我曾见过很多很多人盲目地使用(前端)框架,如 React,Angular 或 Vue等等。这些框架提供了许多有意思的东西:它们支持组件化;它们有强大的社区支持;它们有很多(基于框架的)第三方库来解决问题;它们有很多(很好的)第三方组件;它们有浏览器扩展工具来帮助调试;它们适合做单页应用。
Web 技术变化得很快,而最佳技术实践也在不断发展。Uber 的 Web 平台团队开发了 Fusion.js,一个开源的 Web 框架,用于简化 Web 开发,并构建出高性能的轻量级 Web 应用程序。
要使用现代的前端框架,你需要下载开发环境和依赖,编译代码,然后在浏览器上运行。这个是好是坏?究竟是什么导致了这种不必要的复杂性?是因为我们构建的网站太复杂,还是因为框架本身就很复杂?
有一个流传较广的笑话,一个人在stackoverflow中提了一个问题,如何使用javascript实现一个数字与另外一个数字相加。最高票回答是你应该使用jQuery插件,jQuery插件可以做任何事情。 历史总是在重演,以前是jQuery,现在可能是react或vue。不同的框架有不同的应用场景,杀鸡不要用牛刀
Web框架(Web framework)是一种开发框架,用来支持动态网站、网络应用和网络服务的开发。这大多数的web框架提供了一套开发和部署网站的方式,也为web行为提供了一套通用的方法
Ionic 是一个高级的 HTML5 移动端应用框架,也是一个开发混合移动应用的前端框架,旨在让 Web 开发者更轻松地构建、测试、部署和监控跨平台应用。Ionic 基于 Angular 语法,之前一直不支持 Vue 和 React 。
最近想找一个简单的.Net下的轻量级Web框架,作为用户的本地的一个WebServer,实现同浏览器程序的一些简单交互,并调用本地服务,实现类似浏览器插件的功能。它有如下几点要求:
内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!