- 投稿日:
Proxy headerを設定しないとiOS Safari環境で上手くアクセスできないケースがあるのでやる設定
確認環境
Env | Ver |
---|---|
nginx | 1.19.8 |
サンプルコード
httpセクション
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
リバースプロキシ設定
location @prox {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_pass https://example.com;
}
- 投稿日:
確認環境
Env | Ver |
---|---|
next | 11.1.2 |
typescript | 4.3.4 |
サンプルコード
__mocks__/next/router.ts
export const useRouter = () => {
return {
route: '/',
pathname: '',
query: '',
asPath: '',
push: jest.fn(),
replace: jest.fn(),
events: {
on: jest.fn(),
off: jest.fn(),
},
beforePopState: jest.fn(() => null),
prefetch: jest.fn(() => null),
};
};
- 投稿日:
Babelとtscどっちがいいのか気になったので調べて見たメモ
結論から言うと基本的にはtscで良い
確認環境
Env | Ver |
---|---|
@babel/cli | 7.14.5 |
@babel/core | 7.14.6 |
@babel/preset-env | 7.14.7 |
@babel/preset-typescript | 7.14.5 |
typescript | 4.3.2 |
Babelとは何か?
What is Babel? よりBabelとはJavaScriptのコンパイラと説明されている
Babelがしてくれること
- 構文の変換
- corejsを使ったPolyfill
- ソースコードの変換(codemods
- その他色々
基本的にはES6+をES6にしてくれると考えれば良さそうです
でもそれって別にtscでもいいいよねって思う
Babelの導入
基本はこれ
npm i -D @babel/core @babel/cli @babel/preset-env
Babelの設定
.babelrc
を作ってその中にJSONを書いていく
こんな感じ
{
"presets": [
[
"@babel/preset-env",
{
"targets": {
"edge": "17",
"ie": "11",
"safari": "11.1"
},
"useBuiltIns": "usage",
"corejs": 3
}
]
]
}
Babelの機能について
コンポーネント
@babel/cli
BabelのCLI、これがないと始まらない
@babel/core
Babel本体、CLIがよしなにしてくれる
@babel/preset-env
構文の変換やPolyfillを設定できる
@babel/preset-typescript
TSをトランスパイルしてくれる
BabelとBrowserlist
BabelはBrowserlistの設定を認識して自動でPolyfillを挿入してくれます
なお、Babel 7.4.0以前では設定方法が異なる可能性があります
サンプルコード
IE11をターゲットにした設定のサンプルです
以下のコマンドを流せばPolyfillされたJSが出ることを確認できます
npx babel src -d dest --extensions ".ts"
.babelrc
{
"presets": [
["@babel/preset-env", { "corejs": 3, "useBuiltIns": "usage" }],
["@babel/preset-typescript"]
]
}
.browserlist
ie 11
Babelとtscでトランスパイルしてみる
割と違うコードが出てきます
元のソース
const sp = new URLSearchParams('?aaa=bbb&ccc');
console.log(sp);
const prm = new Promise((res) => res(true));
console.log(prm);
[...Array(10)].forEach((_, i) => console.log(i));
console.log(globalThis.Date());
export {};
Babel
.babelrc
{
"presets": [["@babel/preset-env"], ["@babel/preset-typescript"]]
}
ビルド結果
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true,
});
function _toConsumableArray(arr) {
return (
_arrayWithoutHoles(arr) ||
_iterableToArray(arr) ||
_unsupportedIterableToArray(arr) ||
_nonIterableSpread()
);
}
function _nonIterableSpread() {
throw new TypeError(
"Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."
);
}
function _unsupportedIterableToArray(o, minLen) {
if (!o) return;
if (typeof o === "string") return _arrayLikeToArray(o, minLen);
var n = Object.prototype.toString.call(o).slice(8, -1);
if (n === "Object" && o.constructor) n = o.constructor.name;
if (n === "Map" || n === "Set") return Array.from(o);
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))
return _arrayLikeToArray(o, minLen);
}
function _iterableToArray(iter) {
if (
(typeof Symbol !== "undefined" && iter[Symbol.iterator] != null) ||
iter["@@iterator"] != null
)
return Array.from(iter);
}
function _arrayWithoutHoles(arr) {
if (Array.isArray(arr)) return _arrayLikeToArray(arr);
}
function _arrayLikeToArray(arr, len) {
if (len == null || len > arr.length) len = arr.length;
for (var i = 0, arr2 = new Array(len); i < len; i++) {
arr2[i] = arr[i];
}
return arr2;
}
var sp = new URLSearchParams("?aaa=bbb&ccc");
console.log(sp);
var prm = new Promise(function (res) {
return res(true);
});
console.log(prm);
_toConsumableArray(Array(10)).forEach(function (_, i) {
return console.log(i);
});
console.log(globalThis.Date());
tsc
tsconfig.json
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"allowJs": true,
"checkJs": true,
"sourceMap": true,
"outDir": "./dist",
"strict": true,
"noImplicitAny": true,
"moduleResolution": "node",
"isolatedModules": true,
"baseUrl": ".",
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true
},
"include": ["src/**/*"]
}
ビルド結果
"use strict";
var __spreadArray = (this && this.__spreadArray) || function (to, from) {
for (var i = 0, il = from.length, j = to.length; i < il; i++, j++)
to[j] = from[i];
return to;
};
Object.defineProperty(exports, "__esModule", { value: true });
var sp = new URLSearchParams('?aaa=bbb&ccc');
console.log(sp);
var prm = new Promise(function (res) { return res(true); });
console.log(prm);
__spreadArray([], Array(10)).forEach(function (_, i) { return console.log(i); });
console.log(globalThis.Date());
//# sourceMappingURL=index.js.map
結論
tscで問題ない
tscの方が綺麗なコードが出てきてるので、Polyfill要らなければtscで問題ないです
因みにES6+をES5にするのもできるのでJSのトランスパイルにも使えます
core-jsを使うならBabel
ちょいちょい触っててBabelの利点はcore-js
があれば.browserlist
を使えるので、そこでターゲットを指定してやればPolyfillを勝手に差し込んでくれるところですね
但しCRAではBabelに対する.browserlistはほぼ無価値
あとはCreate React AppはビルドにBabelを採用しているので、FW側でビルドパイプラインがあるときには採用したほうが楽です
(態々書き換える意味もないので)
ただreact-scripts 4.0.3
にはcore-js
が入っていないので、基本的に.browserlist
を書いたところでPolyfillは入らないため、あんまり存在感はないです
- 投稿日:
Webpackには次の2つの開発モードがあるdevelopment, production
開発モードの設定
mode
プロパティに'development'
, 'production'
, 'none'
を設定する
これを設定するとprocess.env.NODE_ENV
で値を取得できる様になる
それぞれの違いは mode-development にあるが、試してみた感じproductionは出力が最適化され、console系が消えるものと思われる
noneを設定するとminifyとかがされてない生のコードが出てくる
webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
+ mode: 'development',
entry: {
index: './src/index.js',
print: './src/print.js',
},
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist'),
clean: true,
},
plugins: [
new HtmlWebpackPlugin({
title: 'Webpack',
template: 'index.html'
})
]
};
- 投稿日:
基本的なバンドルの続き
複数JSの個別バンドル
src/print.js
を追加して、関係するファイルも幾らか変更する
src/print.js
export const printMe = () => {
console.log('I get called from print.js!');
}
src/index.js
import _ from 'lodash';
-import './index.css';
-import Icon from './icon.png';
+import { printMe } from './print';
function component() {
+ window.onload = printMe;
const div = document.createElement('div');
div.innerHTML = _.join(['Hello', 'webpack'], ' ');
- div.classList.add('hello');
-
- const img = document.createElement('img');
- img.src = Icon;
- div.appendChild(img);
return div;
}
document.body.appendChild(component());
webpack.config.js
const path = require('path');
module.exports = {
- entry: './src/index.js',
+ entry: {
+ index: './src/index.js',
+ print: './src/print.js',
+ },
output: {
- filename: 'bundle.js',
+ filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist'),
},
- module: {
- rules: [
- {
- test: /\.css$/i,
- use: ['style-loader', 'css-loader'],
- },
- {
- test: /\.(png|svg|jpg|jpeg|gif)$/i,
- type: 'asset/resource',
- },
- ],
- },
};
この状態でバンドルするとindex.bundle.jsとprint.bundle.jsが生えてくるが、前回バンドルした残骸が残ってしまう
バンドル時に出力フォルダをクリーンアップする
webpack.config.js
const path = require('path');
module.exports = {
entry: {
index: './src/index.js',
print: './src/print.js',
},
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist'),
+ clean: true,
},
};
バンドルした内容をHTMLに反映する
この時点のindex.htmlはdist/bundle.jsを参照しているので、今回の結果が反映されていません
これが反映されるように修正します
npm i -D html-webpack-plugin
webpack.config.js
const path = require('path');
+const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: {
index: './src/index.js',
print: './src/print.js',
},
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist'),
clean: true,
},
+ plugins: [
+ new HtmlWebpackPlugin({
+ title: 'Webpack',
+ })
+ ]
};
これで設定したバンドルファイルがindex.htmlに反映されるようになりました
HTMLのテンプレートを用意する
しかし先程の設定では出力されるHTMLにどうしても限界があります
HtmlWebpackPlugin のリファレンスを見ることである程度なんとかなりますが、テンプレートに差し込むこともできます
次のように変えることでテンプレートHTMLにバンドルを差し込むことが確認できます
webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: {
index: './src/index.js',
print: './src/print.js',
},
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist'),
clean: true,
},
plugins: [
new HtmlWebpackPlugin({
title: 'Webpack',
+ template: 'index.html'
})
]
};
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
- <title>Getting Started</title>
</head>
<body>
<script src="dist/bundle.js"></script>
+ <h1>Webpack</h1>
</body>
</html>