公司:Shopify
Shopify Inc.是加拿大的一家跨国电子商务公司,总部位于安大略省渥太华,Shopify也是该公司所有的电子商务平台的名称。Shopify为在线零售商提供一整套服务“包括支付、市场营销、运输和客户契合工具,以简化小型商户开设在线商店的过程”。
根据公司披露的文件,截止2019年6月,Shopify平台在大约175个国家或地区有超过一百万笔业务,2020日历年的商品总成交额1196亿美元,较2019年增长96%。
Tophat: Crafting a Delightful Mobile Developer Experience
Insight into how Shopify created a seamless one-click manual testing experience (known as "tophatting") for mobile applications by creating a macOS app.
How to Introduce Composite Primary Keys in Rails
One line of code can 5x your Rails application performance. What if you could make a small change to your database design that would unlock massively more efficient data access? At Shopify, we dusted off some old database principles and did exactly that with the primary Rails application.
Improving Shopify App’s Performance
As an integral part of Shopify's ecosystem, our mobile app serves millions of merchants around the world every single day. It allows them to run their business from anywhere and offers vital insights…
A Packwerk Retrospective
In September, 2020, our team at Shopify released a Ruby gem named Packwerk, a tool to enforce boundaries and modularize Rails applications. Since its release, Packwerk has taken on a life of its own, inspiring blog posts, conference talks, and even an entire gem ecosystem. Its popularity is an indication that Packwerk clearly filled a void in the Rails community.
Packwerk is a static analysis tool, similar to tools like Rubocop and Sorbet. Applied to a codebase, it analyzes constant references to help decouple code and organize it into well-defined packages.
But Packwerk is more than just a tool. Over the years, Packwerk’s approach to modularity has come to embody distinct and sometimes conflicting perspectives on code organization and its evolution. Packwerk’s feedback can change the entire trajectory of a codebase to a degree that distinguishes it from other tools of its kind.
This retrospective is our effort, as the team that developed Packwerk at Shopify, to shine a light on our learnings working with the tool, concerns about its use, and hopes for its future.
Horizontally scaling the Rails backend of Shop app with Vitess
Shop app horizontally scaled a Ruby on Rails app with Vitess. This blog describes Vitess and our detailed approach for introducing Vitess to a Rails app.
Introducing Ruvy
We’ve recently open sourced a project called Ruvy! Ruvy is a toolchain that takes Ruby code as input and creates a WebAssembly module that will execute that Ruby code. There are other options for creating Wasm modules from Ruby code. The most common one is ruby.wasm. Ruvy is built on top of ruby.wasm to provide some specific benefits. We created Ruvy to take advantage of performance improvements from pre-initializing the Ruby virtual machine and Ruby files included by the Ruby script as well as not requiring WASI arguments to be provided at runtime to simplify executing the Wasm module.
WASI is a standardized collection of imported Wasm functions that are intended to provide a standard interface for Wasm modules to implement many system calls that are present in typical language standard libraries. These include reading files, retrieving the current time, and reading environment variables. To provide context for readers not familiar with WASI arguments, WASI arguments are conceptually similar to command line arguments. Code compiled to WASI to read these arguments is the same code that would be written to read command line arguments for code compiled to target machine code. WASI arguments are distinct from function arguments and standard library code uses the WASI API to retrieve these arguments.
Building a ShopifyQL Code Editor
In October 2022, Shopify released ShopifyQL Notebooks, a first-party app that lets merchants analyze their shop data to make better decisions. It puts the power of ShopifyQL into merchants’ hands with a guided code editing experience. In order to provide a first-class editing experience, we turned to CodeMirror, a code editor framework built for the web. Out of the box, CodeMirror didn’t have support for ShopifyQL–here’s how we built it.
Sidekick’s Improved Streaming Experience
In this post, learn how Shopify's Sidekick solves markdown rendering jank and response delay in LLM chatbots with buffering parser and async content resolution.
Contributing support for a Wasm instruction to Winch
A month ago I landed a pull request to Winch, Wasmtime's baseline (non-optimizing) compiler, to add support for a number of WebAssembly instructions. Shopify is working on Winch to make Wasm compilation faster. I learned a number of important parts of the codebase and how to test the changes I made which I'll outline below.
Adding support for a WebAssembly instruction means that when Winch encounters a given instruction, it emits zero or more native machine code instructions to perform the operation while ensuring the WebAssembly stack is in the correct state and that CPU registers are appropriately allocated or freed.
Adventures in Garbage Collection: Improving GC Performance in our Massive Monolith
At the beginning of this year, we ran several experiments aimed at reducing the latency impact of the Ruby garbage collector (GC) in Shopify's monolith. Everything described in this article was a team effort, huge thanks to Jason Hiltz-Laforge for his extended knowledge of our production platform, to Peter Zhu for his deep knowledge of the Ruby garbage collector, as well as to Matt Valentine-House, Étienne Barrié, and Shane Pope for their contributions to this work.
In this article we'll talk about the changes we made to improve GC performance, and more importantly, how we got to these changes.
The work consisted of several rounds of improving logging and metrics, interpreting those to form a hypothesis around a change which would be beneficial, testing and shipping that change, and then evaluating whether it should be kept, tweaked, or reverted.
While the narrative in this article might make it seem like we went straight from problem to result, there were several dead ends, incorrect assumptions, and experiments which did not produce the expected results. All as you would expect from an optimization exercise on a dynamic and complex system.
Lessons From Linguistics: i18n Best Practices for Front-End Developers
Here are a few internationalization (i18n) best practices to help front-end developers avoid errors and serve more robust text content on multilingual websites and apps.
Unlocking Real-time Predictions with Shopify's Machine Learning Platform
Learn how Shopify Data built new online inference capabilities into its Machine Learning Platform to deploy and serve models for real-time prediction at scale.
Improving the Developer Experience with the Ruby LSP
Ruby has an explicit goal to make developers happy. Historically, working towards that goal mostly meant having rich syntax and being an expressive programming language—allowing developers to focus on business logic rather than appeasing the language’s rules.
Today, tooling has become a key part of this goal. Many modern languages, such as TypeScript and Rust, have rich and robust tooling to enhance the programming experience. That’s why we built the Ruby LSP, a new language server that makes coding in Ruby even better by providing extra Ruby features for any editor that has a client layer for the LSP. In this article, we’ll cover how we built the Ruby LSP, the features included within it, and how you can install it.
The Case Against Monkey Patching, From a Rails Core Team Member
Monkey patching is considered one of the more powerful features of the Ruby programming language. However, by the end of this post I’m hoping to convince you that they should be used sparingly, if at all, because they are brittle, dangerous, and often unnecessary. I’ll also share tips on how to use them as safely as possible in the rare cases where you do need to monkey patch.
The 25 Percent Rule for Tackling Technical Debt
Let’s talk about technical debt. Let’s talk about practical usable approaches for actually paying it down on a daily, weekly, monthly, and yearly basis. Let’s talk about what debt needs to be fixed now versus what can wait for better planning.
The Complex Data Models Behind Shopify's Tax Insights Feature
The intensive data work behind Shopify's Tax Insights feature required building functionality to handle dynamically changing information.