Je pense qu'il y a pas mal de gens qui développent principalement Ruby et Rails et disent "Je ne comprends pas vraiment JS". Mais tant que le navigateur est là, l'humanité ne peut pas échapper à JS. Cet article a été écrit pour aider les rubistes qui ne sont pas bons en JS à se faire des amis avec webpack.
Si vous savez ce qu'est Webpacker, il sera certainement utile, donc si vous ne le savez pas, veuillez le lire. Si je suis un développeur Rails qui ne connaît pas JS, j'aimerais savoir qui sont Webpack et Webpacker.
――Pourquoi nous utilisons webpack (premier semestre)
Tout d'abord, ** webpack et webpacker sont différents **. ** webpack est un package JS npm **. J'ai grandi dans la communauté JS. npm est un outil de gestion de packages qui peut être utilisé avec Node.js, c'est-à-dire un bundler dans Ruby. Les développeurs JS utilisent tous ce npm ou son fil alternatif. Et ** webpacker est un joyau Ruby **. Rails a également ** simplifié l'utilisation du Webpack **. Ainsi, en sachant qui est le webpack principal, vous pouvez également savoir ce que le webpacker veut faire. Alors, qu'est-ce qu'un webpack?
En un mot, «qu'est-ce qu'un webpack» est généralement expliqué comme ** module bundler **. Module bundler ……? Cela n'a pas de sens. Le monstre Ultraman peut avoir eu un tel nom. Cependant, même si vous regardez le livre illustré du monstre, l'explication du module bundler n'est écrite nulle part.
Je peux comprendre le sentiment que "** les gens de JS ne sont pas amicaux, JS n'est pas un langage pour moi. Je vivrai avec des classes ouvertes, method_missing et monkey patchs **", mais mes sentiments Veuillez écouter l'histoire.
Un regroupeur de modules sert à regrouper des modules. Attendez, je n'ai encore rien expliqué. Veuillez écouter un peu plus.
Si vous deviez créer une application Web d'une taille raisonnable avec Rails, vous auriez probablement beaucoup de fichiers dans ce projet. Certaines classes sont écrites dans ces fichiers et des méthodes sont écrites. Peut-être que la classe est également dans un module.
Par exemple, comme ça. Il s'agit d'un code fictif qui semble être courant dans Rails. C'est un contrôleur qui semble afficher une page permettant à l'administrateur d'importer des informations utilisateur dans un fichier CSV en bloc.
admin/import_users_controller.rb
module Admin
class ImportUsersController < ApplicationController
# [GET] /admin/import_users(.:format)
def index
#Traiter quelque chose A
end
end
end
À propos, tout en ajoutant des fonctions, j'ai créé un tel contrôleur dans un endroit complètement différent du code ci-dessus.
user/import_users_controller.rb
module User
class ImportUsersController < ApplicationController
# [GET] /user/import_users(.:format)
def index
#Quelque chose de traitement B
end
end
end
J'ai deux contrôleurs nommés ʻImportUsersController` dans différents modules. Y a-t-il un problème? …… Il n'y a pas de problème. C'est parce que les espaces de noms sont séparés par module.
C'est un exemple un peu convaincant, mais même lorsque vous dites "Je veux vraiment appeler le contenu d'Admin dans un autre module!" En spécifiant ʻAdmin :: ImportUsersController`, il est possible de l'appeler. Ce n'est pas grave si vous le faites.
Ce genre de chose que Ruby peut prendre pour acquis a longtemps été difficile à faire avec JS. Ce que je ne pouvais pas faire spécifiquement, c'était que je ne pouvais pas simplement diviser les modules et séparer les portées entre les modules. Même si les fichiers étaient séparés, si plusieurs fichiers étaient lus en même temps, les noms seraient facilement en conflit.
"JS a-t-il une portée mondiale?"
Non, ce n'est pas si loin. Même dans l'ancienne JS, il y avait une portée non globale pour le moment. ** Portée de la fonction **. Qu'est-ce qu'une portée de fonction? C'est une portée dans laquelle les variables déclarées dans une fonction ne sont pas accessibles de l'extérieur.
Ancien JavaScript.js
var globalScope = "Portée mondiale";
function hogeFunc() {
var functionalScope = "Quel que soit le nom de variable que vous donnez à la fonction, il ne sera pas écrasé de l'extérieur";
}
L'ancien JS n'avait même pas de mécanisme de séparation d'espace de noms de type module Ruby ni même de syntaxe de classe. Par conséquent, les gens utilisent leur sagesse et utilisent des étendues de fonction pour utiliser des étendues de fonction pour créer une ** syntaxe mystérieuse merdique appelée «fermetures» ** et ** des fantômes entre parenthèses appelées «fonctions immédiates» **. Je l'ai créé et j'ai réussi à le tromper. Mais c'est du passé.
JS est trop douloureux pour avoir à utiliser une syntaxe désagréable pour éviter la pollution globale, mais les génies du monde sont naturellement coupés, et l'impatience des trois vertus majeures du programmeur est le pouvoir de l'améliorer. J'ai essayé de créer JS. Afin d'améliorer l'expérience de développement chez JS, chaque développeur a commencé à formuler des spécifications JS. À la suite de la création de spécifications par chaque développeur avec «le JS le plus puissant auquel j'ai pensé» à chaque endroit, divers mécanismes de module sont créés.
Tous définissent la grammaire pour résoudre le module. Ceux qui survivent encore sont «CJS» et «ESM». Je vais vous expliquer comment importer des modules ** grosso modo **.
Du point de vue historique, je pense que vous le voyez souvent dans Node.js. C'est comme ça.
const a = require('./AnotherFile.js');
a.anotherFileMethod();
En écrivant de cette manière, il est désormais possible de séparer les fichiers sans polluer l'espace de noms. Veuillez noter qu'il est différent de ** // = require` dans Sprockets **.
ECMAScript Module
ECMAScript est, en gros, la spécification JavaScript la plus formelle. La grammaire qui y est définie. Il est normal de penser que cela deviendra courant à l'avenir.
import a from './AnotherFile.js';
a.anotherFileMethod();
Cette méthode vous permet également de séparer les fichiers sans polluer l'espace de noms. Puisque l'explication est assez compliquée, veuillez vous référer à un autre article, etc. pour une utilisation détaillée.
C'est pourquoi tous les développeurs JS sont satisfaits de la modularisation de leur code. J'ai une chose que je veux résoudre, mais j'ai plusieurs spécifications, mais ** c'est une question triviale, alors fermez les yeux **. Je suis heureux.
Tout comme Ruby a CRuby, mruby et JRuby, JS a diverses implémentations. Tout comme Ruby n'en est pas un, JS l'est aussi.
Chaque entreprise a son propre moteur JS, tel que ** V8 ** installé dans Chrome, ** Spider Monkey ** dans Firefox et ** Chakra ** dans Internet Explorer. Vous disposez d'implémentations individuelles pour interpréter JS lui-même. Ces moteurs sont également utilisés en dehors du navigateur. Par exemple, il est également utilisé dans Node.js et JScript sous Windows. C'est une forme dans laquelle d'autres fonctions sont ajoutées au moteur d'origine. Il semble que partout a récemment convergé vers le V8 de Google, mais laissons cela pour l'instant.
** Le problème est IE. ** ** Maintenant [même Microsoft a arrêté le support IE dans Office 365](https://blogs.windows.com/japan/2020/08/18/microsoft-365-apps-say-farewell-to- Il était très peu probable qu'internet-explorer-11 /) interrompe le support d'IE il y a cinq ou six ans.
Pensez-y, même si vous dites: "J'ai ajouté une nouvelle grammaire aux spécifications JS!", Les spécifications ne sont que des spécifications, et si vous ne les implémentez pas, vous ne pourrez pas en parler. Si vous dites "** Ajoutez le module ECMAScript au chakra d'IE. Veuillez ☆ **", Microsoft l'ajoutera-t-il? Au contraire, si vous êtes un dirigeant de Microsoft, pouvez-vous décider de dépenser beaucoup d'argent pour l'implémenter? Je développe déjà un nouveau navigateur, Edge.
C'est pourquoi ** ni le module ECMAScript ni CommonJS [ne fonctionnent] dans IE (https://caniuse.com/mdn-javascript_statements_import). ** **
** Je ne veux certainement pas écrire une syntaxe merdique comme des fermetures ou des fonctions immédiates, même si la nouvelle grammaire est là. ** ** ** Mais je dois également exécuter le code dans IE. ** ** Pour résoudre un tel dilemme, les développeurs ont une fois de plus réduit leur sagesse. "Si tel est le cas, ne serait-ce pas bien s'il y avait un outil de développement qui pourrait bien combiner ce qui a été écrit dans un module moderne en un seul fichier afin qu'il puisse être lu dans IE?"
Cet outil de développement est ainsi! !! !! C'est ** webpack **!
L'image ci-dessous n'est pas faite par moi, c'est juste un scoop de Webpack officiel HP.
J'ai l'impression que différents types de fichiers sont compilés et que cela semble être js ou css.
En fait, les frères Rubist qui ont essayé de générer un fichier statique en exécutant la commande bin / webpack
à portée de main peuvent avoir ressenti cela.
Mais ** ne vous méprenez pas. webpack n'est pas un compilateur. C'est un bundler de modules. ** **
Comme je l'ai écrit plus tôt, webpack résout les dépendances de fichiers basées sur «import» d'ESM et «require» de CJS, et en fait un nouveau fichier JS qui peut être lu par IE. Il n'a pas la capacité de compiler sass en css ou TypeScript en JavaScript.
Regardez de plus près l'image. Il dit "regroupez vos scripts" en haut. Ce n'est pas "compilez vos scripts".
(* Pour faciliter la communication, je dis souvent "un fichier JS", mais ce n'est pas un fichier qui est réellement généré, mais plusieurs fichiers sont lus de manière asynchrone. Cependant, «import» et «require» ont disparu du fichier généré)
Cependant, lorsque j'exécute la compilation avec webpacker, TypeScript devient en fait du JavaScript qui peut être lu même dans IE, et sass devient css qui fait du bien. Cela signifie que vous pouvez également compiler avec webpack.
En fait, webpack peut utiliser une bibliothèque externe pour compiler ** comme pré-processus, puis regrouper les modules. ** Cette bibliothèque s'appelle loader
.
Par exemple, il existe des packages npm tels que ts-loader
pour TypeScript et sass-loader
pour Sass.
En définissant le chargeur sur webpack, webpack peut comprendre que "utilisez d'abord" ts-loader "pour convertir TypeScript en JavaScript, puis résolvez le module." Par conséquent, vous pouvez générer un seul fichier JavaScript groupé à partir de plusieurs fichiers qui étaient à l'origine TypeScript.
Il y a tellement de loaders juste sur le site officiel du webpack, et si vous faites de votre mieux, vous pouvez créer le vôtre.
Vous pouvez définir plusieurs chargeurs. Par exemple, comme ça.
Afin de traiter cela dans l'ordre à partir de 1, il est nécessaire de l'écrire dans webpack.config.js dans le bon ordre. ** Le tableau du chargeur dans webpack.config est traité en premier à partir du dernier chargeur, donc placez le chargeur que vous souhaitez traiter en premier à la fin du tableau. ** **
js:webpack.config.concept de js
use: [
{ loader: 'style-loader' }, //(4e)
{ loader: 'css-loader' }, //(Le troisième)
{ loader: 'postcss-loader' }, //(La deuxième)
{ loader: 'sass-loader' } //(Première)
]
Jusqu'à présent, je ne parlais que de JS, mais tout à coup il y a eu une histoire sur CSS, et le site officiel de webpack a une extension d'image écrite dessus, donc je pense que certaines personnes pourraient être surprises. ** Vous n'êtes pas obligé de tout comprendre **, alors jetez un œil au code React + TypeScript ci-dessous ** en quelque sorte **.
React+Code TypeScript(Fichier avec extension tsx)
import React from "react";
import style from "./Layout.module.css"; //point! importation de css
const Layout: React.FC = ({ children }) => {
return (
<div className={style.app}>
<div className={style.appContainer}>{children}</div>
</div>
);
};
export default Layout;
En plus de générer du HTML côté serveur Rails, de nos jours, en utilisant React et Vue, le HTML peut être généré du côté JS du front-end. Dans ce cas, webpack devrait également être capable de lire du code sous la forme «.jsx», «.tsx» et «.vue». C'est peut-être une extension inconnue, mais c'est comme une variante de .js
.
Le but de ce code est ** d'importer des fichiers CSS du côté JS (bien que TS soit un exemple) **. Aujourd'hui, les styles et les images sont également importés du côté JS, donc ** webpack a des cibles pour résoudre les dépendances autres que JS et TS **. Sinon, vous ne pourrez pas convertir ces programmes afin qu'ils puissent être lus par IE.
Mais gardez à l'esprit que webpack résout les dépendances autour de JS. Veuillez penser que c'est comme un bonus de prendre en charge l'importation CSS, etc.
Outre le chargeur, il existe également un plugin. Un plugin dans webpack est distinct d'un chargeur. Le chargeur effectue le prétraitement, tandis que le plugin peut effectuer le traitement après le regroupement, c'est-à-dire après qu'il est devenu un fichier JS. Par exemple, la réduction de la taille du fichier du JS généré s'appelle ** minify **, et je pense que terser-webpack-plugin
est connu comme un plug-in qui le minifie.
Cliquez ici pour une liste de plugins sur le site officiel du webpack.
Si vous utilisez ** raw webpack au lieu de webpacker **, ajoutez d'abord le chargeur ou le plugin que vous souhaitez utiliser à votre projet avec yarn add
ou npm install
(comme l'installation du bundle de la version JS) est). Après cela, définissez quoi utiliser et comment l'utiliser dans le fichier de configuration webpack tel que webpack.config.js
. Cet article est destiné à vous donner un aperçu, je n'entrerai donc pas dans les détails sur la façon de le configurer. Voir un autre article ou la page Web officielle du pack.
La page officielle est également en anglais, mais il existe de nombreuses méthodes d'introduction. (Par exemple, terser-webpack-plugin)
Je vais le résumer une fois.
--webpack peut résoudre require
et ʻimport` et mettre les fichiers ensemble afin qu'ils puissent être lus par IE.
Bien sûr, vous pouvez faire diverses choses en ajoutant un chargeur et un plugin ainsi qu'en compilant TS et minify de JS, mais je l'ai écrit concrètement ici pour une compréhension facile.
«** Je ne comprends pas du tout JS. Je ne veux pas que les programmeurs Rails configurent webpack.config.js. Veuillez le configurer. Webpack.config.js lui-même est difficile en premier lieu ... **» As-tu déjà pensé? Webpacker est un joyau qui crée une atmosphère qui semble résoudre des problèmes aussi courants (je ne dis pas que cela sera résolu).
D'ailleurs, webpacker facilite l'utilisation de webpack dans les projets Rails, comme décrit dans son README. Jetez un œil au webpacker package.json. package.json agit également comme un Gemfile dans la gestion des packages npm de votre projet. (Il existe divers autres rôles)
package à l'intérieur de webpaker.json
//Abréviation
"dependencies": {
//* Seuls ceux qui sont relativement faciles à comprendre sont extraits.
"babel-loader": "^8.1.0",
"core-js": "^3.6.5",
"css-loader": "^5.0.0",
"file-loader": "^6.1.1",
"mini-css-extract-plugin": "^1.0.0",
"optimize-css-assets-webpack-plugin": "^5.0.4",
"postcss": "^8.1.3",
"postcss-loader": "^4.0.4",
"sass-loader": "^10.0.3",
"style-loader": "^2.0.0",
"terser-webpack-plugin": "^4.0.0",
"webpack": "^4.44.1",
//Abréviation
}
En regardant cela, il semble que divers chargeurs (sass-loader
etc.) et plugins ( terser-webpack-plugin
etc.) sont déjà ** déjà inclus ** dans dépendances
!
(Ts-loader
n'est pas inclus au début, mais comme vous pouvez le voir dans la documentation officielle du webpacker, bundle Il semble entrer lorsque vous tapez une commande comme exec rails webpacker: install: typescript
.)
En lisant le fichier de configuration yml spécifique à Webpacker appelé config / webpacker.yml
, webpacker décide quoi faire et comment le faire, et vous écrit le fichier.
Par exemple, config / webpacker.yml
a un élément appelé ʻextract_css`. En définissant cet élément sur true, CSS peut être exporté en tant que fichier distinct de JS.
webpacker.yml
production:
<<: *default
extract_css: true
Jetons un coup d'œil au code du webpacker pour voir ce qui se passe lorsque ʻextract_css` est vrai.
Code dans Webpaker
// ...réduction...
const styleLoader = {
loader: 'style-loader'
}
// ...réduction...
//use est un tableau d'objets. unshift est une méthode qui ajoute un élément au début d'un tableau.
if (config.extract_css) {
use.unshift(MiniCssExtractPlugin.loader)
} else {
use.unshift(styleLoader)
}
Si config.extract_css
est vrai, vous savez que MiniCssExtractPlugin.loader
est lu en tant que chargeur. Puisque webpack résout essentiellement les dépendances autour de JS, il s'agit essentiellement de CSS in JS
. mini-css-extract-plugin
est un package npm qui vous permet d'exporter CSS dans JS
CSS en un seul fichier CSS. Bien qu'il soit nommé plugin, ici le processus est ajouté au début en tant que chargeur. (MiniCssExtractPlugin est un plugin, mais il doit également être défini comme un chargeur)
Par contre, si false, vous pouvez voir que {loader: 'style-loader'}
est ajouté au début. style-loader
est le chargeur nécessaire pour réellement dessiner CSS dans JS
dans le DOM.
Je vais l'écrire plusieurs fois parce que c'est important, mais ** le tableau des chargeurs dans webpack.config est traité dans l'ordre du dernier chargeur **. Donc, ajouter un paramètre au début d'un tableau signifie le faire à la fin du chargeur. ʻExtract_css: Si vous le définissez sur true, vous pouvez voir que le traitement final du chargeur exécute
mini-css-extract-plugin`, et par conséquent, CSS est écrit.
mini-css-extract-plugin
peut être dans un package différent à l'avenir, mais que fait webpacker.yml et comment webpacker facilite la configuration de webpack Je pense que vous le comprenez.
config/webpack/environment.js
Il existe une autre façon de configurer le Webpacker. Il s'agit d'une méthode fournie par le côté Webpacker et décrit la différence par rapport au paramètre par défaut de Webpacker. Cela doit être écrit en gardant à l'esprit webpack.config.js par rapport aux paramètres de yml. En écrivant dans environment.js, par exemple, vous pouvez ajouter un autre chargeur au début ou à la fin du chargeur.
Si vous êtes un développeur Rails au travail, vous devez savoir à 100%. Surtout ** si la personne qui libère ne sait pas, il y a un risque d'être très douloureux **. Comme vous le savez probablement, webpacker est inclus à partir de Rails6. En utilisant webpacker, je dois savoir comment le code que j'ai écrit est traité et quels artefacts sont déployés dans l'environnement de production ... Par exemple, une erreur s'est produite pendant ou immédiatement après le déploiement de production pour une raison quelconque. Parfois, il n'est pas possible de le dépanner ou d'éliminer la cause première. Le problème avec ** webpacker est qu'il est plus difficile d'identifier le problème qu'avec le webpack ** brut. C'est parce qu'il est difficile de comprendre quel type de webpack.config sera à la fin. Je ne pense pas que ce soit un problème si vous écrivez le code comme passe-temps, mais si vous avez un client et que vous obtenez "Je ne peux pas déployer un correctif de bogue", le client attend ** Buchigire **. ..
"Je ne sais rien pendant la construction des assets: précompilation pour le déploiement en production, mais la compilation a échoué !!!" "Pourquoi cette erreur!"
Error: write EPIPE
at ChildProcess.target._send (internal/child_process.js:806:20)
at ChildProcess.target.send (internal/child_process.js:676:19)
at ChildProcessWorker.send (/XXX/hoge/releases/XXXXXXXXXXXXXX/node_modules/terser-webpack-plugin/node_modules/jest-worker/build/workers/ChildProcessWorker.js:299:17)
"Il semble que quelque chose a échoué au" TerserPlugin "du webpacker effectuant JS minify."
"Cela semble être une erreur qui a tendance à se produire lorsque la mémoire est insuffisante lors de l'examen."
"Quand je vois / var / log / messages
, OOM Killer tue le processus de nœud."
"Pourquoi la mémoire est épuisée ... N'y a-t-il pas d'autre choix que d'augmenter les spécifications du serveur juste pour la construction ...?"
"Les artefacts de construction que Webpack conserve en mémoire sont énormes."
"Comment puis-je réduire plus efficacement les artefacts de construction?"
"Oh, il semble que si vous mettez SplitChunksPlugin
dans le webpack, il sera plus petit!
"Lorsque j'accède au site immédiatement après le déploiement, une erreur mystérieuse apparaît et le plein écran ne s'affiche pas !!!" "Pourquoi cette erreur!"
ActionView::Template::Error: Webpacker can't find application.css
in /XXX/hoge/releases/20XXXXXXXXXXXX/public/packs/manifest.json
"Il n'y a pas d'application.css dans Honma ...? Pourquoi?"
"Il semble que ce css soit toujours implémenté par le" MiniCssExtractPlugin "du webpacker lorsqu'il est défini sur ʻextract_css: true." "Même si css n'est pas bon, je meurs en essayant d'appeler css avec
stylesheet_pack_tag'application' sur le côté mince." "Css a été écrit jusqu'à présent, mais pourquoi est-il soudainement sorti?" "Ah, le composant Vue qui est devenu du code mort et a été effacé ... Vous étiez ... Le CSS a toujours été écrit par webpacker ..." "A l'origine, c'était un gros travail, ʻextract_css: false
et supprimer stylesheet_pack_tag'application'
"Une fois résolu avec ça"
Si vous connaissez dans une certaine mesure webpack, vous serez meilleur pour le dépannage lors de la création de webpack, comme dans l'exemple ci-dessus, et vous pourrez éviter de devenir un guerrier des heures supplémentaires car vous ne pouvez pas déployer. Vous aurez moins peur des boîtes noires lors du déploiement. Inversement, si vous n'aviez aucune connaissance de Webpack et travailliez sur le débogage, il faudrait des jours pour déterminer la cause du problème.
webpacker semble rendre webpack facile, mais si vous ne connaissez pas bien webpack, vous risquez de finir par avoir du mal en cas d'urgence. ** webpacker simplifie la configuration lors du déploiement de webpack, mais cela ne signifie pas que vous pouvez abandonner votre compréhension de webpack **. Lorsque vous continuez à utiliser Webpacker dans un environnement de production, vous le comprendrez sûrement. Je pense qu'une option est de décoller le webpacker et d'utiliser le webpack brut.
J'espère que Webpack se sent un peu plus proche de vous. Si vous ne comprenez toujours pas du tout Webpack, je suis désolé pour mon manque de puissance.
L'histoire de JS est assez grossièrement simplifiée. En dehors de cela, je ne suis ni dans Microsoft ni en train de développer ES, il peut donc y avoir des inexactitudes. Puis, en réalité, un autre bundler de modules est sorti avant webpack, et la grammaire JS a complètement changé depuis ES2015, et les portées de bloc sont sorties en plus des portées de fonction, mais cela semble s'écarter du sujet principal. Je l'ai omis. Après cela, la construction avec webpack n'était pas seulement pour IE, mais avait également un avantage en termes de vitesse d'affichage des pages sous HTTP / 1.1. Maintenant que HTTP / 2 est répandu, je ne connais pas l'avantage de la vitesse. Il y a beaucoup d'endroits où j'ai fait beaucoup de choses par souci de simplicité, mais je pense qu'ils sont "généralement assortis", alors pardonnez-moi à moins que j'aie fait une erreur fatale.
Résolvons avec moi tout en regardant l'erreur Webpack. Il vaut mieux ne pas faire d'erreur!
Recommended Posts