mithril.js v2.0.0-rc.8 Release Notes

Release Date: 2019-07-12 // almost 5 years ago
  • ๐Ÿฑ ๐Ÿšจ๐Ÿšจ๐Ÿšจ This is the final release candidate. There will be no more breaking changes added between now and when v2.0.0 stable is released. What you see here is precisely what to expect from v2.0.0 beyond small bug fixes. ๐Ÿšจ๐Ÿšจ๐Ÿšจ

    ๐Ÿ›  Few new bug fixes, but a few major breaking changes since v2.0.0-rc.7.

    • require("mithril/redraw") now returns the m.redraw function directly. There is no longer any redrawService exposed in any way. #2458
    • m.version no longer exists. In general, rely on feature detection, not version detection. #2466
    • The m.route.link method has been replaced with the m.route.Link component, with a capital L. #2469
    • The m.route.prefix method has been made a property instead. #2469

    And a couple new features:

    • You can use m.route.SKIP to skip a route from onmatch. #2469
    • It's now safe to require("mithril") in environments that lack a full DOM implementation. You just need a few of the globals defined, even if just to null or undefined, to ensure proper instantiation. #2469

    ๐Ÿ’ฅ Breaking changes

    • API: Component vnode children are not normalized into vnodes on ingestion; normalization only happens if and when they are ingested by the view (#2155 (thanks to @magikstm for related optimization #2064))
    • API: m.redraw() is always asynchronous (#1592)
    • API: m.mount() will only render its own root when called, it will not trigger a redraw() (#1592)
    • ๐Ÿ‘ API: Assigning to vnode.state (as in vnode.state = ...) is no longer supported. Instead, an error is thrown if vnode.state changes upon the invocation of a lifecycle hook.
    • API: m.request will no longer reject the Promise on server errors (eg. status >= 400) if the caller supplies an extract callback. This gives applications more control over handling server responses.
    • hyperscript: when attributes have a null or undefined value, they are treated as if they were absent. #1773 (#2174)
    • ๐Ÿ“œ API: m.request errors no longer copy response fields to the error, but instead assign the parsed JSON response to error.response and the HTTP status code error.code.
    • hyperscript: when an attribute is defined on both the first and second argument (as a CSS selector and an attrs field, respectively), the latter takes precedence, except for class attributes that are still added together. #2172 (#2174)
    • render: Align custom elements to work like normal elements, minus all the HTML-specific magic. (#2221)
    • cast className using toString (#2309)
    • โšก๏ธ render: call attrs' hooks first, with express exception of onbeforeupdate to allow attrs to block components from even diffing (#2297)
    • ๐Ÿšš API: m.withAttr removed. (#2317)
    • ๐Ÿšš request: data has now been split to params and body and useBody has been removed in favor of just using body. (#2361)
    • route, request: Interpolated arguments are URL-escaped (and for declared routes, URL-unescaped) automatically. If you want to use a raw route parameter, use a variadic parameter like in /asset/:path.../view. This was previously only available in m.route route definitions, but it's now usable in both that and where paths are accepted. (#2361)
    • route, request: Interpolated arguments are not appended to the query string. This means m.request({url: "/api/user/:id/get", params: {id: user.id}}) would result in a request like GET /api/user/1/get, not one like GET /api/user/1/get?id=1. If you really need it in both places, pass the same value via two separate parameters with the non-query-string parameter renamed, like in m.request({url: "/api/user/:urlID/get", params: {id: user.id, urlID: user.id}}). (#2361)
    • route, request: m.route.set, m.request, and m.jsonp all use the same path template syntax now, and vary only in how they receive their parameters. Furthermore, declared routes in m.route shares the same syntax and semantics, but acts in reverse as if via pattern matching. (#2361)
    • 0๏ธโƒฃ request: options.responseType now defaults to "json" if extract is absent, and deserialize receives the parsed response, not the raw string. If you want the old behavior, use responseType: "text". (#2335)
    • 0๏ธโƒฃ request: set Content-Type: application/json; charset=utf-8 for all XHR methods by default, provided they have a body that's != null (#2361, #2421)
      • This can cause CORS issues when issuing GET with bodies, but you can address them through configuring CORS appropriately.
      • Previously, it was only set for all non-GET methods and only when useBody: true was passed (the default), and it was always set for them. Now it's automatically omitted when no body is present, so the hole is slightly broadened.
    • ๐Ÿ‘ route: query parameters in hash strings are no longer supported (#2448 @isiahmeadows)
      • It's technically invalid in hashes, so I'd rather push people to keep in line with spec.
    • render: validate all elements are either keyed or unkeyed, and treat null/undefined/booleans as strictly unkeyed (#2452 @isiahmeadows)
      • Gives a nice little perf boost with keyed fragments.
      • Minor, but imperceptible impact (within the margin of error) with unkeyed fragments.
      • Also makes the model a lot more consistent - all values are either keyed or unkeyed.
    • vnodes: normalize boolean children to null/undefined at the vnode level, always stringify non-object children that aren't holes (#2452 @isiahmeadows)
      • Previously, true was equivalent to "true" and false was equivalent to "".
      • Previously, numeric children weren't coerced. Now, they are.
      • Unlikely to break most components, but it could break some users.
      • This increases consistency with how booleans are handled with children, so it should be more intuitive.
    • route: key parameter for routes now only works globally for components (#2458 @isiahmeadows)
      • Previously, it worked for route resolvers, too.
      • This lets you ensure global layouts used in render still render by diff.
    • redraw: mithril/redraw now just exposes the m.redraw callback (#2458 @isiahmeadows)
      • The .schedule, .unschedule, and .render properties of the former redrawService are all removed.
      • If you want to know how to work around it, look at the call to mount in Mithril's source for m.route. That should help you in finding ways around the removed feature. (It doesn't take that much more code.)
    • ๐Ÿ“ฆ api: m.version has been removed. If you really need the version for whatever reason, just read the version field of mithril/package.json directly. (#2466 @isiahmeadows)
    • route: m.route.prefix(...) is now m.route.prefix = .... (#2469 @isiahmeadows)
      • This is a fully fledged property, so you can not only write to it, but you can also read from it.
      • This aligns better with user intuition.
    • ๐Ÿšš route: m.route.link function removed in favor of m.route.Link component. (#2469 @isiahmeadows)
      • An optional options object is accepted as an attribute. This was initially targeting the old m.route.link function and was transferred to this. (#1930)
      • The new component handles many more edge cases around user interaction, including accessibility.
      • Link navigation can be disabled and cancelled.
      • Link targets can be trivially changed.
    • API: Full DOM no longer required to execute require("mithril"). You just need to set the necessary globals to something, even if null or undefined, so they can be properly used. (#2469 @isiahmeadows)
      • This enables isomorphic use of m.route.Link and m.route.prefix.
      • This enables isomorphic use of m.request, provided the background: true option is set and that an XMLHttpRequest polyfill is included as necessary.
      • Note that methods requiring DOM operations will still throw errors, such as m.render(...), m.redraw(), and m.route(...).

    ๐Ÿ†• News

    • ๐Ÿ‘ Mithril now only officially supports IE11, Firefox ESR, and the last two versions of Chrome/FF/Edge/Safari. (#2296)
    • ๐Ÿ”€ API: Introduction of m.redraw.sync() (#1592)
    • API: Event handlers may also be objects with handleEvent methods (#1949, #2222).
    • ๐Ÿ“œ API: m.request better error message on JSON parse error - (#2195, @codeclown)
    • โฑ API: m.request supports timeout as attr - (#1966)
    • ๐Ÿ‘ API: m.request supports responseType as attr - (#2193)
    • ๐Ÿคก Mocks: add limited support for the DOMParser API (#2097)
    • ๐Ÿ‘ API: add support for raw SVG in m.trust() string (#2097)
    • ๐Ÿšš render/core: remove the DOM nodes recycling pool (#2122)
    • render/core: revamp the core diff engine, and introduce a longest-increasing-subsequence-based logic to minimize DOM operations when re-ordering keyed nodes.
    • ๐Ÿ“„ docs: Emphasize Closure Components for stateful components, use them for all stateful component examples.
    • API: ES module bundles are now available for mithril and mithril/stream (#2194 @porsager).
      • All of the m.* properties from mithril are re-exported as named exports in addition to being attached to m.
      • m() itself from mithril is exported as the default export.
      • mithril/stream's primary export is exported as the default export.
    • fragments: allow same attrs/children overloading logic as hyperscript (#2328)
    • route: Declared routes may check against path names with query strings. (#2361)
    • ๐Ÿ‘ route: Declared routes in m.route now support - and . as delimiters for path segments. This means you can have a route like "/edit/:file.:ext". (#2361)
      • Previously, this was possible to do in m.route.set, m.request, and m.jsonp, but it was wholly untested for and also undocumented.
    • ๐Ÿ— API: m.buildPathname and m.parsePathname added. (#2361)
    • route: Use m.mount(root, null) to unsubscribe and clean up after a m.route(root, ...) call. (#2453)
    • render: new redraw parameter exposed any time a child event handler is used (#2458 @isiahmeadows)
    • route: m.route.SKIP can be returned from route resolvers to skip to the next route (#2469 @isiahmeadows)

    ๐Ÿ› Bug fixes

    • API: m.route.set() causes all mount points to be redrawn (#1592)
    • ๐Ÿ’… render/attrs: Using style objects in hyperscript calls will now properly diff style properties from one render to another as opposed to re-writing all element style properties every render.
    • ๐Ÿšš render/attrs All vnodes attributes are properly removed when absent or set to null or undefined #1804 #2082 (#1865, #2130)
    • render/core: Render state correctly on select change event #1916 (#1918 @robinchew, #2052)
    • โšก๏ธ render/core: fix various updateNodes/removeNodes issues when the pool and fragments are involved #1990, #1991, #2003, #2021
    • render/core: fix crashes when the keyed vnodes with the same key had different tag values #2128 @JacksonJN (#2130)
    • render/core: fix cached nodes behavior in some keyed diff scenarios #2132 (#2130)
    • ๐Ÿšš render/events: addEventListener and removeEventListener are always used to manage event subscriptions, preventing external interference.
    • render/events: Event listeners allocate less memory, swap at low cost, and are properly diffed now when rendered via m.mount()/m.redraw().
    • render/events: Object.prototype properties can no longer interfere with event listener calls.
    • ๐Ÿšš render/events: Event handlers, when set to literally undefined (or any non-function), are now correctly removed.
    • ๐Ÿ›  render/hooks: fixed an ommission that caused oninit to be called unnecessarily in some cases #1992
    • ๐Ÿ“„ docs: tweaks: (#2104 @mikeyb, #2205, @cavemansspa, #2250 @isiahmeadows, #2265, @isiahmeadows)
    • render/core: avoid touching Object.prototype. __proto__ setter with key: " __proto__" in certain situations (#2251)
    • render/core: Vnodes stored in the dom node supplied to m.render() are now normalized #2266
    • ๐Ÿ’… render/core: CSS vars can now be specified in {style} attributes (#2192 @barneycarroll), (#2311 @porsager), (#2312 @isiahmeadows)
    • request: don't modify params, call extract/serialize/deserialize with correct this value (#2288)
    • render: simplify component removal (#2214)
    • ๐Ÿšš render: remove some redundancy within the component initialization code (#2213)
    • ๐Ÿ‘€ API: mithril loads mithril/index.js, not the bundle, so users of mithril/hyperscript, mithril/render, and similar see the same Mithril instance as those just using mithril itself.
      • https://unpkg.com/mithril is configured to receive the minified bundle, not the development bundle.
      • The raw bundle itself remains accessible at mithril.js, and is not browser-wrapped.
      • Note: this will increase overhead with bundlers like Webpack, Rollup, and Browserify.
    • ๐Ÿ›  request: autoredraw support fixed for async/await in Chrome (#2428 @isiahmeadows)
    • โšก๏ธ render: fix when attrs change with onbeforeupdate returning false, then remaining the same on next redraw (#2447 @isiahmeadows)
    • โšก๏ธ render: fix internal error when onbeforeupdate returns false and then true with new child tree (#2447 @isiahmeadows)
    • ๐Ÿ›  route: arbitrary prefixes are properly supported now, including odd prefixes like ?# and invalid prefixes like #foo#bar (#2448 @isiahmeadows)
    • โ†ช request: correct IE workaround for response type non-support (#2449 @isiahmeadows)
    • render: correct contenteditable check to also check for contentEditable property name (#2450 @isiahmeadows)
    • ๐Ÿ“„ docs: clarify valid key usage (#2452 @isiahmeadows)
    • route: don't pollute globals (#2453 @isiahmeadows)
    • request: track xhr replacements correctly (#2455 @isiahmeadows)