カテゴリー
未分類

ElectronのshowOpenDialogSync()メソッドを、fitler指定してコールしたのに、拡張子の制限が反映されない。

原因は、拡張子を配列で指定していないことでした。

ファイル選択ダイアログ表示する際に、選択対象をPDFファイルだけに制限しようと考えて、以下のような誤ったコードを書いていました。

dialog.showOpenDialogSync({
  filters: [
    {name: 'PDFファイル', extensions: 'pdf'} //これは誤りです。
    ]
});

しかしながら上記のコードでは、以下の画像のようにPDF以外のファイルも選択候補になります。

期待したのは、以下の画像のようにPDFファイルだけが選択候補となる事です。

正しくは、以下のようにextensionsに配列を記述すべきでした。

//これは誤りです。
dialog.showOpenDialogSync({
  filters: [
    {name: 'PDFファイル', extensions: ['pdf']}//正しくは、このように配列として渡します
    ]
});

今から考えると、extensionsという言葉自体が複数形なので、分かりそうなものですが、作業中は気づかず少し困っていました。

['jpg', 'jpeg'] のような、複数の拡張子を持つファイルであれば、もっと意識したかもしれませんね。

同じようにお困りの方のお役に立てれば幸いです。

公式ドキュメントを読んでみると、他にありがちなミスで、'pdf'と書くべきところを*.pdfと書いてしまったり、.pdfと書いてしまったりするケースが紹介されていました。

https://www.electronjs.org/docs/api/dialog

The extensions array should contain extensions without wildcards or dots (e.g. 'png' is good but '.png' and '*.png' are bad). To show all files, use the '*' wildcard (no other wildcard is supported).

https://www.electronjs.org/docs/api/dialog

extensions配列は、ワイルドカードやドットは含めないでください。(例えば、'png'は正しいですが、'.png''*.png'はダメです)。

全てのファイルを表示するには'*'ワイルドカードを使います。(他の種類のワイルドカードは、どれもサポートされません)

カテゴリー
未分類

TypeScript Error TS2307: Cannot find module ‘fs’. was resolved by installing the @types/node package. [2020]

Node.js has many useful built-in modules.

The fs module to handle the file system is one of them.

In TypeScript, it seems that @types/node is needed to use these modules provided by Node.js.

To add the @types/node package, run the following command.

npm install --save-dev @types/node

More details

I tried to write a little useful program in TypeScript, so I created a tool folder by executing the following commands in sequence.

I installed the TypeScript module and created an empty index.ts file.

mkdir tool
cd tool
npm init -y 
npm install typescript
touch index.ts

Since the index.ts file is empty to begin with, I used a text editor to write the following and saved it.

import * as fs from 'fs';
fs.writeFileSync('a.txt', 'b')

Then I ll compile it with the following command.

npx tsc index.ts 

At this stage, an error has occurred.

The errors that occurred are as follows.

index.ts:1:21 - error TS2307: Cannot find module 'fs'.


1 import * as fs from 'fs';
                      ~~~~




Found 1 error.

It should have created the index.js file automatically, but due to this error, it was not created.

The error message says that the fs module is not found.

The fs module is already bundled with Node.js.
If I wrote the code in JavaScript, I did not need to do any special preparation to use it.

However, in order to write code in TypeScript, a suitable type definition file seems to be needed.

So, run the following command as described above.

npm install --save-dev @types/node

Then we’ll try compiling again.

npx tsc index.ts 

Then the index.js file will be created successfully.

Let’s run the index.js file by the node command.

node index.js

Then an a.txt file will be created, and if the string “b” is written in it, it is as intended.

So TypeScript might not know what Node.js standard library has. And it seems to me that it’s the @types/node package that tells you that.

カテゴリー
未分類

In the sudo npm install -g xxx command, ‘sudo’ seems to be deprecated. [2019]

To install the Vue CLI and to install Angular CLI, you can find the following commands on their official websites.

npm install -g @vue/cli
npm install -g @angular/cli

However, when I actually ran the above command, I got an Error: EACCES: permission denied, access '/usr/local/lib/node_modules'.

npm WARN checkPermissions Missing write access to /usr/local/lib/node_modules
npm ERR! path /usr/local/lib/node_modules
npm ERR! code EACCES
npm ERR! errno -13
npm ERR! syscall access
npm ERR! Error: EACCES: permission denied, access '/usr/local/lib/node_modules'
npm ERR!  { [Error: EACCES: permission denied, access '/usr/local/lib/node_modules']
npm ERR!   stack:
npm ERR!    'Error: EACCES: permission denied, access \'/usr/local/lib/node_modules\'',
npm ERR!   errno: -13,
npm ERR!   code: 'EACCES',
npm ERR!   syscall: 'access',
npm ERR!   path: '/usr/local/lib/node_modules' }
npm ERR! 
npm ERR! The operation was rejected by your operating system.
npm ERR! It is likely you do not have the permissions to access this file as the current user
npm ERR! 
npm ERR! If you believe this might be a permissions issue, please double-check the
npm ERR! permissions of the file and its containing directories, or try running
npm ERR! the command again as root/Administrator (though this is not recommended).

According to various online sources, using the sudo command seems to solve the problem for the time being.

sudo npm install -g @vue/cli

However, the error message ended with the following notation.

the command again as root/Administrator (though this is not recommended).

Apparently, the npm development team doesn’t really recommend to use the sudo command.

So what is the ideal form?

The official Node.js installer is not recommended.

I searched the npm documentation site and found the following description

We do not recommend using a Node installer, since the Node installation process installs npm in a directory with local permissions and can cause permissions errors when you run npm packages globally.

https://docs.npmjs.com/downloading-and-installing-node-js-and-npm

You can download the Node installer from the Node.js official site.

(By the way, the official Node.js site and the official npm site are two different sites.)

This installer installs the npm command as well as the node command.

The problem is where to install the npm command. In this way, by default, each time you use the npm install -g command, you get a permission error.

My environment was also built using the Node installer and I had same problem.

To solve this problem, the official npm website seems to recommend using the Node installer itself instead of using the sudo command.

So what do you recommend using to install npm?

Installing Node.js using the Node Version Manager

The above document says the following (in bold)

 you must install Node.js and the npm command line interface using either a Node version manager or a Node installer. We strongly recommend using a Node version manager to install Node.js and npm.

https://docs.npmjs.com/downloading-and-installing-node-js-and-npm

There are several ways to install the Node.js and npm.

One way is to use the Node installer, but this is not recommended by the npm team.

The other way to install is to use the Node version manager.

So what is the Node Version Manager?

Node version manager

Node Version Manager is a software that allows multiple versions of Node.js to be installed on a single computer.

For example, you can install two versions of the software, v10.15.3 and v12.1.0, and switch between them as needed.

As you can see, the software was originally designed to switch between multiple versions, but there is another advantage to using Node version manager.

The Node version manager installs the npm command in a folder that does not require special permissions.

This allows you to use the npm install -g command without having to use sudo.

Node Version Manager, which one to install?

In truth, the phrase “install the node’s version manager” is not very appropriate.

This is because there is no software named “Node version manager”.

Just as there are Chrome and Firefox in the “Browser” category, and you can use whatever you want, the Node version manager has multiple software programs, such as nvm and nodist, each developed by a different team.

You can choose one of them, install it and use it.

In the above document introduces two versions, one for Linux/Mac and one for Windows.

OSX or Linux Node version managers

Windows Node version managers

Each one will be used slightly differently, so you can install the one you like.

I use Mac, so I decided to install nvm. The operation is intuitive and easy to understand, and I like it.

By the way, I had Node.js that installed by the official Node installer. But I did not uninstall this existing Node.js. I installed nvm additionally.

By using the nvm ls command, we can show a choice of which version of Node.js to use. I found named item “system” appears in the choice. This pointed to the existing Node.js installed from the Node installer.

You can use the nvm use system command to switch to an existing Node.js command, or use the nvm use v10.15.3 command to switch to your v10.15.3 that nvm’s own installation

In addition to the four mentioned, there are several other Node version managers that have been developed. You may want to try them out.

As we participate in more and more front-end projects, we’re seeing more and more “the version of Node.js used in one project is not the same as the version of Node.js used in another project” and so on.

Whether you use the sudo command or not, you should probably try to use the Node version manager.

It’s kind of strange that the official Node.js site and the official npm site have different views on where to install npm, but maybe sooner or later they’ll agree on a discussion.

カテゴリー
未分類

An Error: Call to a member function make() on null in Laravel 8.5 PHPUnit test

When you override the setUP() method on your own, you need to call the parent::setUp() method

In my case, we implemented our own setUp() method, but did not call parent::setUp().

The documentation says the following.

If you define your own setUp / tearDown methods within a test class, be sure to call the respective parent::setUp() / parent::tearDown() methods on the parent class.

https://laravel.com/docs/8.x/testing#creating-and-running-tests

I solved this problem by calling parent::setUp() inside a setUp() method I wrote.

<?php

namespace Tests\Feature;

use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Tests\TestCase;

class UserTest extends TestCase
{
    protected function setUp():void {
        parent::setUp(); //I had to add this line.
        //Custom setups are performed after the setUp() process of the parent class
    }
    protected function tearDown():void {
        //Custom cleanup is performed before the parent class tearDown() process
        parent::tearDown();
    }

    /**
     * A basic feature test example.
     *
     * @return void
     */
    public function testExample()
    {
        $response = $this->get('/');

        $response->assertStatus(200);
    }
}

If you want to provide a tearDown method, you need to use parent::tearDown() as well.

More details

In my case, I had our own setUp() method, but I did not call parent::setUp() as shown below.

<?php

namespace Tests\Feature;

use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Tests\TestCase;

class UserTest extends TestCase
{
    protected function setUp():void {
        //I forgot to write parent::setUp();.
        //Custom setups are performed after the setUp() process of the parent class
    }
    /**
     * A basic feature test example.
     *
     * @return void
     */
    public function testExample()
    {
        $response = $this->get('/');

        $response->assertStatus(200);
    }
}

In this state, an error occurred when calling $this->get(‘/’).

1) Tests\Feature\UserTest::testExample
Error: Call to a member function make() on null

/var/www/vendor/laravel/framework/src/Illuminate/Foundation/Testing/Concerns/MakesHttpRequests.php:498
/var/www/vendor/laravel/framework/src/Illuminate/Foundation/Testing/Concerns/MakesHttpRequests.php:292
/var/www/tests/Feature/UserTest.php:21

Laravel provides its own useful features for automated testing.

In my case , $this->get(‘/’), is one such example.

A test class created by artisan make:test command is prepared to use such a useful feature.

php artisan make:test UserTest

This test class does not have a setUp() method by default.

In this state, PHPUnit will execute the setUP() method of the parent class. This sets up some useful features.

However, if you implement the setUp() method on your own, it will not do what it is supposed to do in the parent class.

To fix this, we need to write a manual call to the setUp() method of the parent class.

カテゴリー
未分類

Laravel 8.5 PHPUnit テスト で Error: Call to a member function make() on null が発生した話

独自にsetUP()メソッドをオーバーライドしたときは、parent::setUp()メソッドをコールする必要がある

今回のケースでは、独自に setUp() メソッドを実装したのに、 parent::setUp() をコールしていなかったことが原因でした。

ドキュメントには、以下の記述があります。

If you define your own setUp / tearDown methods within a test class, be sure to call the respective parent::setUp() / parent::tearDown() methods on the parent class.

もし、あなた独自の setUp / tearDown メソッドをテストクラスに書くときは、それぞれの親クラスについて parent::setUp() / parent::tearDown() をコールすることを忘れないでください。

https://laravel.com/docs/8.x/testing#creating-and-running-tests

自作した setUp() メソッドの内側で parent::setUp() をコールすることで解消しました。

<?php

namespace Tests\Feature;

use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Tests\TestCase;

class UserTest extends TestCase
{
    protected function setUp():void {
        parent::setUp(); //この行を追記する必要がありました。
        //独自の準備処理を親クラスの setUp() 処理のあとに行う
    }
    protected function tearDown():void {
        //独自の後片付け処理を親クラスの tearDown() 処理の前に行う
        parent::tearDown();
    }

    /**
     * A basic feature test example.
     *
     * @return void
     */
    public function testExample()
    {
        $response = $this->get('/');

        $response->assertStatus(200);
    }
}

なお、 tearDownメソッドを用意する場合には、 同様に parent::tearDown() が必要とのことです。

もっと詳しく

今回のケースでは、独自に setUp() メソッドを用意したにもかかわらず、 以下のようにparent::setUp() をコールしていませんでした。

<?php

namespace Tests\Feature;

use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Tests\TestCase;

class UserTest extends TestCase
{
    protected function setUp():void {
        //parent::setUp();を書き忘れている。
        //独自の準備処理を親クラスの setUp() 処理のあとに行う
    }
    /**
     * A basic feature test example.
     *
     * @return void
     */
    public function testExample()
    {
        $response = $this->get('/');

        $response->assertStatus(200);
    }
}

この状態では、 $this->get('/') をコールしたときにエラーが発生しました。

1) Tests\Feature\UserTest::testExample
Error: Call to a member function make() on null

/var/www/vendor/laravel/framework/src/Illuminate/Foundation/Testing/Concerns/MakesHttpRequests.php:498
/var/www/vendor/laravel/framework/src/Illuminate/Foundation/Testing/Concerns/MakesHttpRequests.php:292
/var/www/tests/Feature/UserTest.php:21

Laravel では、自動テストに便利な機能を独自に用意してくれています。

今回のコードの $this->get('/') もその一つです。

artisan make:test コマンドで作成したテストクラスでは、このような便利機能を使う準備がされています。

php artisan make:test UserTest

このテストクラスには、初期状態では setUp() メソッドが存在していません。

この状態では、PHPUnit は親クラスの setUP() メソッドを実行します。これにより、便利な機能がいくつか準備されます。

しかし、 setUp() メソッドを独自に実装した場合は、親クラスで行うはずの処理が行われません。

これを解消するために、手作業で親クラスの setUp() メソッドをコールする記述が必要となります。

カテゴリー
未分類

Running laravel on laradock apache2

In the official laradock documentation, there is a lot of sample code to run nginx, but laradock also provides a mechanism to use apache.

Getting Started

First of all, if there is a service that is running, let’s bring it down, to prevent troublesome troubles.

docker-compose down

Create the following localhost.conf file in the laradock/apache2/sites folder on the host OS side.

laradock/apache2/sites/localhost.conf

<VirtualHost *:80>
  ServerName localhost
  DocumentRoot /var/www/public/
  Options Indexes FollowSymLinks

  <Directory "/var/www/public/">
    AllowOverride All
    <IfVersion < 2.4>
      Allow from all
    </IfVersion>
    <IfVersion >= 2.4>
      Require all granted
    </IfVersion>
  </Directory>

</VirtualHost>
This is what the image looks like.

Then record the localhost.conf file to your Docker image with the following command:

docker-compose build apache2

Now you are ready to go.

Start the container in the same way as for nginx, but specify the apache2 service instead of the nginx service

docker-compose up -d apache2 mysql

More details

There is a difference in the default settings of nginx and apache2 in laradock.

default nginx settings of laradock.

The default setting of nginx of laradock is to make the /var/www/public folder of the OS in the container as Document Root when accessed from http://localhost.

https://github.com/laradock/laradock/blob/master/nginx/sites/default.conf#L13

default apache2 settings of laradock .

On the other hand, in apache2 of laradock, when accessing with http://localhost, the /var/www folder of the OS in the container is set to be published.

If you modify this to expose the /var/www/public folder like nginx, you can develop laravel with the same usability as when using nginx.

/ laradock / apache2 / sites folder

A file called sample.conf.example is provided in the laradock/apache2/sites/ folder.

https://github.com/laradock/laradock/blob/master/apache2/sites/sample.conf.example

I copied this file, pasted as a new file called localhost.conf, and rewrote the following three directories.

  • ServerName
  • DocumentRoot
  • Directory

Note that it works even if the file name is not localhost.conf, but the end of the file name must end with .conf.

In laradock, if you save the * .conf file in the laradock/apache2/sites/ folder on the host OS side, it seems that it is set to be recognized by apache.

カテゴリー
未分類

laradock の apache2 で laravel を動作させる

laradock の 公式ドキュメントでは、nginxを起動するサンプルコードが多いですが、laradock には apache を使う仕組みも用意されています。

操作手順

面倒なトラブルを防ぐため、まずは起動しているサービスがあれば、 down させましょう

docker-compose down

ホストOS側の laradock/apache2/sites フォルダに、以下のlocalhost.confファイルを新しく作成します。

laradock/apache2/sites/localhost.conf

<VirtualHost *:80>
  ServerName localhost
  DocumentRoot /var/www/public/
  Options Indexes FollowSymLinks

  <Directory "/var/www/public/">
    AllowOverride All
    <IfVersion < 2.4>
      Allow from all
    </IfVersion>
    <IfVersion >= 2.4>
      Require all granted
    </IfVersion>
  </Directory>

</VirtualHost>
このようなイメージとなります。

次に、以下のコマンドで localhost.conf ファイルを Dockerイメージに記録します。

docker-compose build apache2

これで準備は完了です。

nginxの時と同じ要領でコンテナを起動しますが、nginx サービスではなく apache2 サービスを指定します

docker-compose up -d apache2 mysql

もっと詳しく

laradock では nginx と apache2 の初期設定に違いがあります。

laradock の nginx の初期設定

laradock の nginx の初期設定 には、http://localhost でアクセスした場合に、コンテナ内のOS の /var/www/public フォルダを公開させる記述があります。

https://github.com/laradock/laradock/blob/master/nginx/sites/default.conf#L13

laradock の apache2 の初期設定

一方、 laradock の apache2 では、http://localhost でアクセスした場合は、コンテナ内のOSの /var/www フォルダを公開する設定となっています。

これを、 nginx と同様に /var/www/public フォルダを公開するように修正すれば、 nginx を利用していた時と同じ使い勝手で laravel を開発できます。

/laradock/apache2/sites フォルダ

laradock/apache2/sites/ フォルダには sample.conf.example というファイルが用意されています。

https://github.com/laradock/laradock/blob/master/apache2/sites/sample.conf.example

このファイルをコピーして、新しく localhost.conf というファイルを追加し、以下の3つのディレクトリを書き換えました。

  • ServerName
  • DocumentRoot
  • Directory

なお、localhost.conf というファイル名でなくても動作はしますが、ファイル名の末尾は、.confで終わる必要があります。

laradock では、 ホスト OS側の laradock/apache2/sites/ フォルダの中に、*.conf ファイルを保存すると、apacheによって認識されるように設定されているようです。

カテゴリー
未分類

laradock で 、ERROR: Named volume “data/minio/data:/export:rw” is used in service “minio” but no declaration was found in the volumes section. というエラーが発生。

.env ファイルにDATA_PATH_HOST=dataと書いてしまっていました。

本当は、以下のように ./data と設定したかったのです。

# Choose storage path on your machine. For all storage systems
DATA_PATH_HOST=./data

それを、以下のように、dataの前の ./ を書き忘れてしまい、標題のようなエラーが発生しました。

# Choose storage path on your machine. For all storage systems
DATA_PATH_HOST=data

DATA_PATH_HOST=./data と書きかえたら、問題が解消されました。

事態が改善するかもしれません。

もっと詳しく

Laradockをインストールした直後は通常、 env-example ファイルを .env というファイル名でコピーします。

その .env ファイルには DATA_PATH_HOST という項目があり、以下のような記述になっています。

# Choose storage path on your machine. For all storage systems
DATA_PATH_HOST=~/.laradock/data

この設定のままだと、MySQLのデータなどが、laradockフォルダの外に保存されます。

それはそれで便利なケースもありますが、プロジェクトごとに laradock フォルダの中にdataフォルダという名前で保存されるように設定しようとしました。

その時に変更するのが、 DATA_PATH_HOST という項目です。

この設定は、.envとは別のファイル、 docker-compose.yaml ファイルの中で、コンテナが使用するボリュームとして使われています。

https://github.com/laradock/laradock/blob/master/docker-compose.yml#L427-L428

### Minio ################################################
    minio:
      build: ./minio
      volumes:
        - ${DATA_PATH_HOST}/minio/data:/export
        - ${DATA_PATH_HOST}/minio/config:/root/.minio

もし、DATA_PATH_HOST の値が ./data ではなく、ただの data だとすると、はこれらの設定は以下のように解釈されます。

### Minio ################################################
    minio:
      build: ./minio
      volumes:
        - data/minio/data:/export
        - data/minio/config:/root/.minio

先頭が/~... など、相対パスとして使う記号から始まるボリュームは、ホストOSのファイルパスだと解釈されます。(今回は、こちらが正解でした。)

しかし、ただ data と書いてしまうと、それはホストOSのファイルパスではなく、「ボリューム名」として解釈されます。

Dockerは、data/minio/data と名付けられたボリュームの設定が、docker-compose.yamlのどこかに記述されていると解釈して探しますが、実際には、そんなものは書かれておらず、今回のエラーとなったようです。

HTMLでの相対パスの書き方とは、考え方が違う

HTMLでの外部ファイルへのリンクでは、先頭の ./ は、あってもなくても同じように動作します。

<script src="script.js"></script>
<script src="./script.js"></script>

しかし、docker-compose.yml の コンテナに使用するボリュームの設定では ./ があればファイルパス、なければ「Named Volume」という、全く異なった解釈となるようでした。

Compose file version 3 reference

https://docs.docker.com/compose/compose-file/#short-syntax-3

カテゴリー
未分類

TypeScript で error TS2307: Cannot find module ‘fs’. が表示された時に、@types/node パッケージをインストールすると解決されました。[2020]

Node.jsには、あらかじめたくさんの便利なモジュールが用意されています。

ファイルシステム(File System)を扱う fs モジュールもその一つです。

TypeScriptで、このNode.jsが提供するモジュールを扱うには、@types/nodeが必要なようです。

@types/node パッケージ を追加するには以下のコマンドを実行します。

npm install --save-dev @types/node

もっと詳しく

TypeScript で、ちょっとした便利プログラムを書いてみようと思い、以下のコマンドを順に実行して、toolフォルダを新しくつくりました。

TypeScriptモジュールがインストールされ、空のindex.tsファイルを作成しました。

mkdir tool
cd tool
npm init -y 
npm install typescript
touch index.ts

index.tsファイルは、もともと空っぽなので、テキストエディタを使って、以下の記述を行い、保存しました。

import * as fs from 'fs';
fs.writeFileSync('a.txt', 'b')

その後、以下のコマンドでコンパイルをします。

npx tsc index.ts 

この段階で、エラーが発生してしまいました。

発生したエラーは次のとおり

index.ts:1:21 - error TS2307: Cannot find module 'fs'.


1 import * as fs from 'fs';
                      ~~~~




Found 1 error.

本来ならばindex.jsファイルが自動的に作成されるはずが、このエラーのため、作成されませんでした。

fs モジュールが見つからないという内容のエラーです。

fs モジュールはNode.jsにもともと同梱されているモジュールで、JavaScriptで記述を行うときには、特に何も準備することなく使用できていました。

ところが、TypeScriptに記述を行うためには、専用の定義ファイルが必要になるようです。

そこで、前述の以下のコマンドを実行します。

npm install --save-dev @types/node

その後、もういちどコンパイル動作を試します。

npx tsc index.ts 

すると、無事index.jsファルをが作成されます。

作成されたindex.jsファイルをnodeコマンドで実行してみましょう。

node index.js

すると、a.txtファイルが作成され、文字列「b」が書き込まれていれば目的通りです。

Node.jsがどんな標準ライブラリを持っているのかを、TypeScriptは知らなかったのですね。それを教えてあげるのが @types/node パッケージだ、ということのようです。

カテゴリー
未分類

sudo npm install -g xxx コマンド の、 ‘sudo’ は、推奨されないようです。[2019]

Vue CLI のインストールAngular CLI のインストール方法は、それぞれの公式サイトで、以下のようなコマンドが紹介されています。

npm install -g @vue/cli
npm install -g @angular/cli

ところが、実際に上記のコマンドを実行してみると、Error: EACCES: permission denied, access '/usr/local/lib/node_modules' が発生しました。

npm WARN checkPermissions Missing write access to /usr/local/lib/node_modules
npm ERR! path /usr/local/lib/node_modules
npm ERR! code EACCES
npm ERR! errno -13
npm ERR! syscall access
npm ERR! Error: EACCES: permission denied, access '/usr/local/lib/node_modules'
npm ERR!  { [Error: EACCES: permission denied, access '/usr/local/lib/node_modules']
npm ERR!   stack:
npm ERR!    'Error: EACCES: permission denied, access \'/usr/local/lib/node_modules\'',
npm ERR!   errno: -13,
npm ERR!   code: 'EACCES',
npm ERR!   syscall: 'access',
npm ERR!   path: '/usr/local/lib/node_modules' }
npm ERR! 
npm ERR! The operation was rejected by your operating system.
npm ERR! It is likely you do not have the permissions to access this file as the current user
npm ERR! 
npm ERR! If you believe this might be a permissions issue, please double-check the
npm ERR! permissions of the file and its containing directories, or try running
npm ERR! the command again as root/Administrator (though this is not recommended).

様々なネットの情報を調べると、sudo コマンド を使えば、ひとまずは解消するようです。

sudo npm install -g @vue/cli

しかしながら、エラーメッセージの末尾には、以下の表記がありました。

the command again as root/Administrator (though this is not recommended).

root もしくは Administrator として、コマンドを再実行してみてください(とはいえ、これはお勧めしません。)

どうやら、 npm の開発チームとしては、 sudo コマンドを使うことは、本望ではないようです。

では、どういった形が理想なのでしょう。

Node.js 公式サイトのインストーラはオススメされない

npmのドキュメントサイトを探した結果、以下の記述を発見しました。

We do not recommend using a Node installer, since the Node installation process installs npm in a directory with local permissions and can cause permissions errors when you run npm packages globally.

Node インストールプロセスはローカルのパーミッションを持つディレクトリに npm をインストールし、あなたがグローバルに npm パッケージを実行するとパーミッションエラーを引き起こす可能性があるので、 Node インストーラを使うことはお勧めしません。

https://docs.npmjs.com/downloading-and-installing-node-js-and-npm

Node.js 公式サイトでは、Node インストーラがダウンロードできます。

(ちなみに、Node.js 公式サイトnpm の公式サイトは、それぞれ別のサイトです。)

このインストーラは、 node コマンドに加え、 npm コマンドも一緒にインストールしてくれます。

ただ、この npm コマンドのインストール先が問題で、デフォルトのままでは、 `npm install -g` コマンドを使うたびに、パーミッションエラーが起こります。

私の環境も、Node インストーラを使って構築したものだったので、この現象が起きていました。

この問題を防ぐためには、sudoコマンドを使うのではなく、Node インストーラを使うこと自体をお勧めしない、というのが、npm の 公式サイトの見解のようです。

では、何を使ってインストールするのが、npmのオススメなのでしょうか。

Node バージョンマネージャ を使ってNode.js をインストールする

先述のドキュメント に、(太字で)以下の記述があります。

 you must install Node.js and the npm command line interface using either a Node version manager or a Node installer. We strongly recommend using a Node version manager to install Node.js and npm.

Nodeバージョンマネージャか、Nodeインストーラのどちらかを使用して、Node.jsとnpmコマンドラインインタフェースをインストールする必要があります。 Node.jsとnpmをインストールするには、Nodeバージョンマネージャを使用することを強く推奨します。

https://docs.npmjs.com/downloading-and-installing-node-js-and-npm

Node.js と npm のセットをインストールする方法は、いくつかあります。

ひとつは、先述の Node インストーラを使う方法ですが、これはnpmチームはオススメしていません。

もう一つのインストール方法は Node バージョンマネージャを使う方法です。

では、 Node バージョンマネージャとは何でしょうか。

Node バージョンマネージャ

Node バージョンマネージャは、一つのコンピュータに、様々なバージョンのNode.jsを複数インストールできるようにしてくれるソフトです。

例えば、 v10.15.3 と v12.1.0 という、二つのバージョンをインストールして、必要に応じて両者を切り替えて使う、ということが可能となります。

このように、もともとは複数バージョンの切り替えを目的としたソフトなのですが、Node バージョンマネージャを使うメリットはもう一つあります。

Node バージョンマネージャは、npmコマンドを、特別なパーミッションを必要としないフォルダにインストールしてくれます。

これにより、sudo を使うことなく、 npm install -g コマンドが使えるようになります。

Node バージョンマネージャ、どれをインストールする?

実は、「Node バージョンマネージャをインストールする」という言葉は、あまり適切ではありません。

というのは、「Node バージョンマネージャ」というソフトがあるワケではないのです。

「ブラウザ」に Chrome や Firefox があって、それぞれ好きなものを使っているように、「Node バージョンマネージャ」には、 nvmnodist など複数のソフトがあって、それぞれのチームが別々に開発しています。

そのうちのどれかを選んでインストールして使う、という形になります。

先述のドキュメント では、Linux/Mac 用と、 Windows 用に2つずつ、紹介されています。

OSX or Linux Node version managers

Windows Node version managers

それぞれ、使い方は微妙に違うと思うので、気に入ったものをインストールするといいです。

私は Macを使っているので nvmをインストールすることにしました。操作が直感的で分かりやすく、気に入っています。

なお、過去にNode インストーラを使ってインストールした 既存の Node.js は、とくにアンインストールせず、追加で nvm をインストールしました。

nvm ls コマンドを使うと、どのバージョンの Node.js を使うのか、選択肢を表示することができるのですが、その選択肢に「system」という項目が現れます。これが、Nodeインストーラからインストールした既存の Node.js をさしていました。

nvm use system コマンドを使うことで、既存の Node.js コマンドに切り替えられるし、 nvm use v10.15.3 コマンドを使うと、nvm が自動的にインストールした v10.15.3 に切り替わります。

紹介されている4つ以外にも、Node バージョンマネージャはいくつか開発されているようです。試してみるのもいいかもしれません。

フロントエンドのお手伝いが増えてくると、「あるプロジェクトで使われているNode.jsのバージョンと、別のプロジェクトで使われている Node.js のバージョンが違う」などということが増えてきます。

sudo コマンドを使うかどうかに関わらず、Node バージョンマネージャを利用していくようにした方がよさそうです。

Node.js 公式サイトと npm の公式サイトとで、npmのインストール先についての見解が違うというのは、なんだか不思議ですが、そのうち話し合いによって、一致されるかもしれませんね。