Tag: JavaScript

"Native code" label

How to detect if a function is a core part of browser API? This way:

  const a = () => {};
  a.toString(); // () => {}
  console.log.toString(); // function log() { [native code] }

You see? [native code] label. Sounds good, right?

  const a = () => {};
  const b = a.bind(null);
  b.toString(); // function () { [native code] }

Oops. But we still have this log name in the string snapshot.

Babel to EsBuild migration for Webpack

Recently I had some time to take a look at the performance of my pet project. One thing bothered me: the project is relatively small, but the bundle size was too big: 780 KiB. Whereas the project had only a few dependencies: react (~10 KiB), react-router (~70 KiB), react-dom (~90 KiB), dayjs (~3 KiB), lodash (~70 KiB). The bundle should not be that big for so few dependencies.

So I ran webpack-dev-analyzer and found a weird thing: the sum of the libs is 3 times smaller than the final bundle size. Then I decided to take a look at @statoscope/webpack-plugin. It was a good tool but it gave me the same result. The bundle has way too much trash.

Ok. Probably it’s just webpack wrappers over 300+ small modules.

Read more

How to migrate Javascript webpack configuration to Typescript

It turned out that the newest versions (at least 5+) of webpack support Typescript out of the box. So the algorithm is next:

  • Create tsconfig.json at the root level. Content:
    {
      "compilerOptions": {
        "module": "CommonJS",
        "target": "ES5",
        "esModuleInterop": true,
        "checkJs": false,
        "strict": true,
      }
    }
    
  • Rename all *.js files to *.ts
  • Type all of them:
    • no more ugly require, use import.
    • webpack package has typings out of the box.
      • You may find these types useful: ConfigurationRuleSetRule
      • To enable devServer write this: 
        interface Configuration extends WebpackConfiguration {
          devServer?: WebpackDevServerConfiguration;
        }
        
    • Some of the popular plugins have types too.
    • Some of them don’t have types at all:
      • Create a *.d.ts file
      • Put there something like this:
        declare module 'postcss-assets' {
          export default function postcssAssets(opts: {
            basePath: string;
            relative: boolean;
          }): unknown;
        }
        
  • Make sure your webpack.config.ts file is placed at the root level. I mean exactly at the same spot where node_modules is. Otherwise, you won’t be able to build it. No compilerOptions helped me. 
  • Run webpack. It should work.

Multilayout Keybinds in a Browser

Imagine that you want to add support of some keybinds in your web application. Let it be Ctrl+L for liking\unliking something. What kind of issues can you face in such a scenario?

CMD or Ctrl?

At first look at Ctrl. Probably on MacOS you’d like to replace it with CMD.  You can check it by event.metaKey.

Extra modificators

Probably you wouldn’t like to consider Ctrl+Alt+S as Ctrl+S. So don’t forget to handle this case.

Different layouts

Not every language that uses the Latin alphabet has the L button at the same position as in a typical English keyboard layout. You need to decide what is more important to you ― a real key position on a keyboard or a letter upon of it. I’d guess that the 2nd case is preferable for most applications. 

To get a real key position you can use which, code, codeKey properties. To get a letter on the key use key property.

Different alphabets

What’s about Greek or Russian alphabets? Or any other possible alphabets? Or not even alphabets? There’re different strategies. And one of them is to use a key from a typical English keyboard layout. So it leads us again to code and codeKey properties.

Example

const getEventKeyBind = event => {
  const keybind = [];

  if (event.metaKey) keybind.push('cmd');
  if (event.ctrlKey) keybind.push('ctrl');
  if (event.shiftKey) keybind.push('shift');
  if (event.altKey) keybind.push('alt');

  if (event.key === ' ') keybind.push('space');
  else {
    const key = event.key.toLowerCase();

    if (key.length !== 1 || key.match(/^[a-z]$/)) {
      // latin key or a special key
      keybind.push(key);
    } else {
      // extra-latin or non-latin key
      const [, enSymbol] = event.code.match(/^Key(\w)$/) || [];
      keybind.push(enSymbol ? enSymbol.toLowerCase() : key);
    }
  }

  return keybind.join('+');
};

Отладка NodeJS приложений при помощи ndb

Пост-заметка об ndb. Всем кто пишет для nodejs периодически приходится отлаживать своё приложение. Да даже тем, кто использует mocha или webpack бывает нет-нет да удобнее отладить по-человечески проблему, нежели тыкать повсюду console.log-и. NodeJS издавна предоставляет нам для этого браузерный инструмент.

Работает оно так:

  • мы запускаем наше приложение из консоли с нужным флагом
  • NodeJS в консоли нам сообщает ссылку с нужным портом
  • Которую мы открываем в браузере и видим перед собой копию chrome-dev-tools-ов.

Если надо перезагрузить приложение ― повторяем всё с нуля. С одной стороны сами инструменты весьма удобные. С другой стороны вся эта мышиная возня с портами и перезапусками очень неудобна.

И тут на помощь к нам приходит ndb. Просто перед командой запуска приложения добавляем ndb. Dev-tools-ы открываются прямо в своём отдельном окне. Перезагрузить приложение можно нажав ctrl+R. Все breakpoint-ы и прочая муть при этом сохраняется. 

Выглядит это всё примерно так: