跳到正文
DEV Community· Andrey Gubanov·· 3 小時前AI 評分38

Matreshka.js 作者回顧 2013 年前端開發的樣貌

I wrote a JavaScript framework in 2013. Here's what that world looked like

AI 導讀

Matreshka.js 作者本月重新帶回這個 2013 年開始開發的雙向數據綁定框架,並藉翻閲舊程式碼回顧當年的前端開發環境。該框架曾在 GitHub 獲得約 900 個星標;當時開發者還須處理 IE 8 等舊瀏覽器的限制及 JavaScript 的 var 陷阱。Matreshka.js 現可用於舊式網站和 AI 生成的單頁 HTML,並備有教導 AI 智能體使用它的技能。

正文

On September 26, 2013, I made the first commit of Matreshka.js, a small framework for two-way data binding. It got about 900 stars on GitHub, lived for years, and then I left it. This month I brought it back. Going through the old code felt like opening a time capsule, so here is what front-end work looked like back then.

Every new project felt like Christmas

In 2013 a new open source project was an event. Backbone.js reached 1.0 that March. AngularJS was the new hot thing, with its "magic" two-way binding. Ember reached 1.0 in August. Knockout had observables. Then, in May, Facebook showed React at JSConf US, and people laughed at JSX: HTML inside JavaScript looked like a step back.

You read the source of each new library to see how it worked. A good idea could change how everyone wrote code the next month. A blog post about a new pattern went around for weeks.

Today it is different. Something new ships every day, and an AI can write a framework in an afternoon. Nobody waits for the next release anymore. Maybe that is fine, but I miss the feeling.

You had to know every browser

"It works in Chrome" meant nothing. Internet Explorer 8 was still everywhere: on office computers, in banks, in government. jQuery 2.0 dropped IE 6, 7 and 8 in April 2013, and the jQuery team had to tell everyone to keep using the 1.x line for those browsers.

So you knew things like these by heart:

  • IE 8 had no addEventListener. It had attachEvent('onclick', …), and the event object came from window.event, with srcElement instead of target.
  • Firefox had no innerText, only textContent. Old IE had no textContent, only innerText.
  • IE 8 had no Array.prototype.indexOf, no forEach, no map, no getElementsByClassName.
  • A trailing comma in an object literal ({ a: 1, }) could break the whole script in old IE.
  • A page could switch IE into an older "Document Mode", and your code had to detect it.

Matreshka is built on getters and setters: assign app.x = 'hi' and the bound input updates. In IE 8, Object.defineProperty existed, but it only worked on DOM objects. So the 2014 Matreshka did something I still find funny. On IE 8, every instance of a Matreshka class was secretly an XDomainRequest, the IE 8 object for cross-domain requests. It is a host object, so defineProperty worked on it. The class code created one and copied the prototype methods onto it:

// IE 8 allows getters and setters only on DOM objects,
// so every instance is secretly an XDomainRequest (an AJAX object)
if (ie8) {
  constructor = function () {
    var r = new XDomainRequest;
    for (var p in constructor.prototype) if (p !== 'constructor') {
      r[p] = constructor.prototype[p];
    }
    realConstructor.apply(r, arguments);
    return r;
  };
}

That is the real code from the repository, July 2014, trimmed a little, comment added. It shipped.

Testing meant virtual machines. Microsoft gave away Windows images with each IE version, and you clicked through your app in every one of them.

You had to know JavaScript itself

There was no let and no const (they came with ES2015). There was var, and you had to know its traps.

var is hoisted:

console.log(x); // undefined, not an error
var x = 5;

var lives in the function, not in the block, so every callback in a loop sees the last value:

for (var i = 0; i < 3; i++) {
  setTimeout(function () { console.log(i); }, 0);
}
// 3 3 3

The fix was a function that runs right away (an IIFE) to capture i. Everyone wrote them.

this got lost all the time:

var user = { name: 'Ann', hi: function () { return this.name; } };
var hi = user.hi;
hi(); // not 'Ann': `this` is the global object now

So every codebase had var self = this; at the top of half the functions. IE 8 had no Function.prototype.bind either.

== had its own rules:

'' == 0    // true
'0' == 0   // true
'' == '0'  // false

And there was with, which people asked about in interviews:

var obj = { a: 1 };
with (obj) {
  a = 2; // obj.a is 2
  b = 3; // obj has no b, so this creates a global variable b
}

with was already forbidden in strict mode, but you still met it in old code and had to read it.

No npm for the front end

npm was for Node. For the browser you downloaded a file, put it in /js/vendor/, and added a <script> tag. The order of the tags mattered: jQuery first, then the plugins, then your code. Bower helped a little. Grunt ran the build: concatenate, minify, done. Gulp came out that year. Matreshka's first build was a Gruntfile.js, a week after the first commit, and the 2014 repo has a bower.json. The 2013 repo even committed its node_modules.

There were no Promises in browsers either. You had callbacks inside callbacks, or jQuery's $.Deferred.

The future that didn't come

Data binding was the big topic, and everyone thought the platform would solve it. Object.observe was going to let any object report its changes, natively, and Chrome shipped it in 2014. Frameworks planned around it. In November 2015 it was withdrawn: hardly anyone used it, and libraries had moved to getters, setters and immutable data. Matreshka was on getters and setters from the start, so it didn't miss it.

Matreshka.js today

I brought it back for the same reason you keep an old photo. But it turned out to have a real job.

Matreshka 3 is a small structural MVC framework for pages that already exist. You take HTML you already have and bind properties to it. There is no build step and no virtual DOM. One <script> tag and about 24 kB gzipped:

<input class="in" type="text">
<output class="out"></output>

<script src="https://cdn.jsdelivr.net/npm/matreshka@3/dist/matreshka.min.js"></script>
<script>
  const app = new Matreshka();
  app.bindNode('x', '.in, .out');
  app.x = 'Hello';
</script>

Two places where this fits:

  • Legacy sites. A server-rendered page with jQuery and no build pipeline. You add structure (models, collections, bindings) without rewriting it in React.
  • Standalone HTML files written by AI. Ask an AI for a small tool or a dashboard, and you often get one HTML file. Matreshka gives that file a structure: data in models, the DOM bound to them, nothing to install.

In both cases an AI agent may be the one writing the code, so there is an agent skill. It teaches your coding agent how to use Matreshka:

npx skills add finom/matreshka

It still supports the browsers jQuery 4 supports, Internet Explorer 11 included. Some habits from 2013 stay.

Docs: matreshka.js.org · Code: github.com/finom/matreshka

來源:DEV Community · dev.to