Add posts
parent
18aed71c18
commit
8ca1ca0588
@ -0,0 +1,56 @@
|
|||||||
|
---
|
||||||
|
title: "Pixelbook Development Mode: A Cautionary Tale"
|
||||||
|
subtitle: It was all going far too well
|
||||||
|
---
|
||||||
|
|
||||||
|
So for about a month I've been using the Pixelbook as my portable development
|
||||||
|
and note-taking laptop, and it's been generally going well. Like I mentioned in
|
||||||
|
my [first impressions](/pixelbook-first-impressions) post, the
|
||||||
|
pen support is great, Android apps run surprisingly well, and while the Linux
|
||||||
|
container has some quirks it's pretty useful overall.
|
||||||
|
|
||||||
|
My biggest complaint so far, is that enabling ChromeOS developer mode puts it
|
||||||
|
it in a state where it's far too easy to accidentally wipe your system. **(Yes,
|
||||||
|
I say this from experience - it just happened to me.)**
|
||||||
|
|
||||||
|
Putting the Pixelbook in developer mode requires disabling its boot-time OS
|
||||||
|
verification, and every time the device starts it splashes up a warning screen
|
||||||
|
to inform you of this fact. The warning screen helpfully recommends you press
|
||||||
|
the spacebar to re-enable OS verification, but neglects to mention that doing
|
||||||
|
so will factory reset the device.
|
||||||
|
|
||||||
|
> *Developer Mode Boot Screen*
|
||||||
|
>
|
||||||
|
> ![Image of Pixelbook stating "OS verification is off"](/images/chromebook-developer-mode-warning.png)
|
||||||
|
>
|
||||||
|
> Source [Android Central](https://www.androidcentral.com/how-enable-developer-mode-chrome-os)
|
||||||
|
|
||||||
|
If developer mode was more stable, this wouldn't really be an issue - the
|
||||||
|
problem comes from when the device reboots unexpectedly.
|
||||||
|
|
||||||
|
This morning I was using my Pixelbook in tablet mode with the keyboard folded
|
||||||
|
behind it. This configuration puts the keys on the exposed bottom face of the
|
||||||
|
device . . . where I was holding it.
|
||||||
|
|
||||||
|
I was moving some windows around when the system froze and restarted, and before
|
||||||
|
I could realize what was happening my Pixelbook started resetting itself. The
|
||||||
|
way I was holding it, the spacebar was depressed (which normally isn't an issue
|
||||||
|
since keyboard input is disabled in tablet mode, but the bootloader isn't smart
|
||||||
|
enough to know that) and within seconds it had cleared the OS verification
|
||||||
|
screen and started the reset.
|
||||||
|
|
||||||
|
Luckily most of my projects are in git and all the Android apps I was using
|
||||||
|
sync to cloud storage automatically, so I didn't end up losing anything. But it
|
||||||
|
definitely made my heart skip a beat when I saw that powerwash screen come up!
|
||||||
|
|
||||||
|
So if you think you'd like to get the latest features, or pehaps you want to
|
||||||
|
sideload some Android apps onto your Pixelbook - whatever it is, think long and
|
||||||
|
hard about the risk of living one crash away from accidentally resetting your
|
||||||
|
device.
|
||||||
|
|
||||||
|
I think Google should potentially make it a bit harder to activate the powerwash
|
||||||
|
function from the bootloader, but developer mode _is_ supposed to be unstable
|
||||||
|
and dangerous. Personally I'll be sticking to the stable branch from now on,
|
||||||
|
so there's not any risk of this happening again. If you decide developer mode
|
||||||
|
is right for you, be sure to back up your work regularly!
|
||||||
|
|
@ -0,0 +1,36 @@
|
|||||||
|
---
|
||||||
|
title: "Adventures with my Pixelbook: Linux Scaling Mode"
|
||||||
|
subtitle: Be warned, it's kind of janky
|
||||||
|
unlisted: true
|
||||||
|
---
|
||||||
|
|
||||||
|
This is just a quick update on one of the largest issues I've had with the
|
||||||
|
ChromeOS Linux app support: display scaling.
|
||||||
|
|
||||||
|
ChromeOS has a display scaling mode for Linux applications that don't handle the
|
||||||
|
high-DPI screen very well, and it generally works okay. It's a bit blurry, but
|
||||||
|
better than having a tiny UI in some applications.
|
||||||
|
|
||||||
|
The downside is that to enable this mode for an app, you need to pin that app
|
||||||
|
to your taskbar.
|
||||||
|
|
||||||
|
I'm not particularly fond of having a full taskbar, so I like to keep just the
|
||||||
|
essentials on there - and what about apps I need to launch with command line
|
||||||
|
parameters? Those can't be pinned to the taskbar without losing that ability.
|
||||||
|
|
||||||
|
If you've run into this issue, then don't worry - there is a solution!
|
||||||
|
|
||||||
|
ChromeOS's Linux container is allowed to draw to the screen through a special
|
||||||
|
X11 server that is run _inside_ the container, and then forwards that image
|
||||||
|
to the Wayland server running in ChromeOS. The magical screen scaling? It's
|
||||||
|
just a second X11 server!
|
||||||
|
|
||||||
|
Therein lies the trick to start apps with window scaling,
|
||||||
|
simply set the `DISPLAY` environment variable to `:1`.
|
||||||
|
|
||||||
|
```shell
|
||||||
|
DISPLAY=:1 firefox
|
||||||
|
```
|
||||||
|
|
||||||
|
Enjoy running your Linux apps without needing a magnifying glass!
|
||||||
|
|
@ -0,0 +1,120 @@
|
|||||||
|
---
|
||||||
|
title: Sample Debugging Write-up
|
||||||
|
subtitle: ''
|
||||||
|
unlisted: true
|
||||||
|
---
|
||||||
|
|
||||||
|
> This is a sample write-up of how I investigated an issue for work.
|
||||||
|
>
|
||||||
|
> I'm putting this up with permisison from my former job, but it is ***unlisted***
|
||||||
|
and I would appreciate if you do not share it around.
|
||||||
|
>
|
||||||
|
> Additionally, code screenshots originally included when sending this write-up
|
||||||
|
to my co-workers have been removed so as to not leak confidential information.
|
||||||
|
Where applicable the document has been lightly re-worded to still make sense.
|
||||||
|
|
||||||
|
## Initial Issue
|
||||||
|
|
||||||
|
To start off with, let's talk about the actual bug. We observed that after
|
||||||
|
deploying a small change (which added a few static files and a URL redirect), our A/B
|
||||||
|
test between versions of the site started to act weird. Several of the pages
|
||||||
|
that had been implemented in the new design would briefly display the old UI,
|
||||||
|
then flash abruptly to the new version.
|
||||||
|
|
||||||
|
This issue was easily reproducible, and from our analytics it appeared
|
||||||
|
to be happening to **all** visitors assigned to the old UI. The weirdest part
|
||||||
|
though was that none of those affected pages were at all related to the changes
|
||||||
|
we had eployed!
|
||||||
|
|
||||||
|
At first I didn't really know what was going on, so I started poking around
|
||||||
|
in the sources for the various pages that manifested this issue. I didn't
|
||||||
|
expect there to be anything there, particularly since none of them had been
|
||||||
|
changed in the bad deploy, but it was a good place to start.
|
||||||
|
|
||||||
|
It's important to note here that our A/B testing for this application was
|
||||||
|
done at least in part at the HTTP routing level. Multiple different Next.js page
|
||||||
|
paths were being remapped by our reverse proxy to the same external URL, and
|
||||||
|
so from the beginning I knew something was rather weird here, as the old design
|
||||||
|
wasn't even importing any of the components of the new design. Just from that
|
||||||
|
we knew this couldn't be a component-level issue, and this had something to
|
||||||
|
do with Next's page routing.
|
||||||
|
|
||||||
|
## Weird behavior in webpack
|
||||||
|
|
||||||
|
After quickly double checking there was nothing obvious in the pages themselves,
|
||||||
|
I opened up the browser debugger and checked to see
|
||||||
|
which component files were being loaded. I thought perhaps there
|
||||||
|
could be an issue where the static cached version of the page was the old design
|
||||||
|
but then on rendering in the client it would reset to the new one.
|
||||||
|
|
||||||
|
While I was there, I happened to see something interesting: both versions of the page
|
||||||
|
were having their JS bundles loaded, and both still had sourcemaps cached in the browser developer tools. This seemed
|
||||||
|
weird to me. If the browser were (for some reason) choosing to reload the tab, it would
|
||||||
|
have unloaded all of the old layout's resources. Seeing both loaded at once
|
||||||
|
indicated that Next was doing a *client side* navigation from one to the other.
|
||||||
|
|
||||||
|
So after noting down that I needed to remind the team to disable sourcemaps in production, I started
|
||||||
|
digging into the debugger and dropping breakpoints.
|
||||||
|
|
||||||
|
## Debugging
|
||||||
|
|
||||||
|
I added a breakpoint to Next's `router.push()` and `router.replace()` functions,
|
||||||
|
just to see if they were being called at all.
|
||||||
|
|
||||||
|
As luck would have it, I was right - the `replace()` function *was* being called
|
||||||
|
immediately after the page's first render.
|
||||||
|
Firefox's debugger even helpfully had a call stack for me, with where it was being called from!
|
||||||
|
|
||||||
|
As I clicked through the call stack I found there was a check somewhere in one
|
||||||
|
of Next's internal components - as part of its `componentDidMount()` function
|
||||||
|
there were a few conditions where it would force-reload the page.
|
||||||
|
|
||||||
|
Because of how it's built, Next's sourcemaps were incomplete in the view I had,
|
||||||
|
but after comparing some of the constants in the file I was able to track it down
|
||||||
|
to the file [next/client/index.js](https://github.com/vercel/next.js/blob/v11.1.0/packages/next/client/index.tsx#L181)
|
||||||
|
in the Next.js source (line 181).
|
||||||
|
|
||||||
|
This section definitely looked like it could be causing the issue - the way Next
|
||||||
|
was figuring out what URL to pass to `router.replace()` was relying on the URL
|
||||||
|
in the browser's location history, which means that it would entirely bypass
|
||||||
|
our reverse proxy A/B routing. Unfortunately I didn't yet know why this was
|
||||||
|
being called, or if it was the only reason the page was being reinitialized.
|
||||||
|
|
||||||
|
I spent a while walking through the conditions in this line one by one, using
|
||||||
|
my debugger to check the value of each variable in the faulty production pages,
|
||||||
|
and work out what exactly was happening. It skips the checks for 404 and error pages,
|
||||||
|
since that's not the kind of page we were on, `isFallback` is false so it moves
|
||||||
|
on to the other conditions combined with an `||` there, `data.nextExport` is
|
||||||
|
undefined (as we don't use static export for our site), but `hydrateProps` and
|
||||||
|
`hydrateProps.__N_SSG` were both set!
|
||||||
|
|
||||||
|
So because `hydrateProps` and `hydrateProps.__N_SSG` both exist, it reloads the
|
||||||
|
page if either of the following conditions are true:
|
||||||
|
|
||||||
|
- The page has a query string (`location.search`)
|
||||||
|
- The environment variable `__NEXT_HAS_REWRITES` is set
|
||||||
|
|
||||||
|
Obviously the pages we first observed the bug on didn't have query strings, but
|
||||||
|
the rewrite condition had been optimized by webpack to just `true` so that seemed promising. With a bit more searching I tracked that
|
||||||
|
environment variable to Next's [webpack config](https://github.com/vercel/next.js/blob/v11.1.0/packages/next/build/webpack-config.ts),
|
||||||
|
which seems to set the variable if Next's config file has a rewrite property configured.
|
||||||
|
|
||||||
|
## Confirming the hunch
|
||||||
|
|
||||||
|
At this point it seemed I had found the issue, but I wanted to confirm it without
|
||||||
|
any doubt. So I reverted my local repo to the last commit we had deployed before
|
||||||
|
seeing the issue, and quickly navigated back to that same line in the generated
|
||||||
|
app bundle. This time the `process.env.__NEXT_HAS_REWRITES` condition had been
|
||||||
|
entirely removed, as webpack saw that environment variable was `false` for the build
|
||||||
|
and could never affect the condition.
|
||||||
|
|
||||||
|
Lastly I spun up my full local environment, reverse proxy and all, just to confirm
|
||||||
|
that in as close to a production-like environment as I could. I removed the rewrite
|
||||||
|
rule from the Next.js application and made an equivalent redirect in our reverse
|
||||||
|
proxy - just to make sure I could preserve the intended application behavior without
|
||||||
|
the bug.
|
||||||
|
|
||||||
|
And sure enough - with the redirect behavior moved out of Next.js and into the reverse
|
||||||
|
proxy, the bug entirely disappeared! So I reverted and restored my changes a few times
|
||||||
|
just to double check, and then alerted the other senior developers I had a solution.
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 216 KiB |
Loading…
Reference in New Issue