Antecedentes
Algumas linhas sobre mim para uma compreensão geral do nível do autor e do problema que está sendo resolvido.Meu nome é Eugene e sou desenvolvedor web frontend junior verde.
Há algum outro ano, trabalhei em um campo completamente diferente e, apenas em teoria, pensei em mudar de profissão, mas por volta de dezembro de 2018 encontrei meu caminho e comecei a atuar.
Após cerca de seis meses de treinamento total, consegui um emprego como programador front-end. Aprendi coisas fundamentais (eu acho que sim), js, interação com o DOM, reagir + redux. HTML e CSS pelo menos + uma compreensão geral de bootstrap e assembly, trabalhando com git, a linha de comando.
Além da teoria, foram feitos alguns projetos de treinamento, incluindo um bate-papo sobre react + redux, além de algumas tentativas de implementar algumas de suas idéias.
Em geral, um cavalheiro moderno padrão é o ponto de partida para uma frente iniciante.
Na primeira semana e meia, montei uma máquina virtual, há muito de tudo e tudo é desconhecido e incompreensível para mim.
No processo, eu me familiarizo com novas ferramentas e tecnologias: com bancos de dados (e me coloco outro marcador na lista "aprender"), massa, wincsp, etc.
Passe com sucesso nesta pista de obstáculos e vá para a frente.
Prefácio
Depois de escrever meu reloader e este artigo, encontrei análogos, incluindo os de
Habré . No entanto, ele decidiu publicar sua bicicleta.
Iniciar
Temos um projeto bastante grande, herdado, escrito em angularJS, com todos os seus encantos. Depois do React, ele parecia um dinossauro para mim, mas nada, eu compro cursos de angularjs, rapidamente dirijo e começo a me beneficiar.
Uma impressão positiva é que o projeto foi bem escrito, por pessoas com braços claramente retos. Variáveis com excelente nomenclatura clara, a estrutura é a mesma em todos os lugares e, em geral, toda a lógica é muito acessível e simplesmente expressa.
Mas existem desvantagens suficientes.
O primeiro problema: o projeto está sendo construído por algum minimizador antigo e é impossível usar a sintaxe js moderna. Nenhum () => {}, const res = [... dados, subRes], assíncrono / aguardado ...
O segundo problema: não há webpack, nem mesmo pelo menos gole, e, portanto, também não há um servidor webpack-dev familiar para mim com sua excelente recarga a quente.
Escreveu. Salvo. F5 Inconvenientemente. Dor? Não é uma dor direta, mas muito desconfortável.
O terceiro problema: criar o arquivo .bat do projeto, no qual parte do projeto é simplesmente copiada, parte das bibliotecas são coletadas sem minimização, parte é minimizada em um arquivo e o restante dos arquivos do projeto em outro. Lista de bibliotecas no terceiro arquivo. Lista de arquivos a serem construídos no quarto. E assim por diante
O quarto problema: todas as bibliotecas estão ordenadamente na pasta libs e são conectadas por um script em index.html. Tudo, exceto expresso e proxy para ele (eles não estão envolvidos na montagem, mas apenas para o desenvolvimento).
E longe de qualquer lugar, existem versões ou uma indicação de uma biblioteca específica.
Eu vivi treinando em um belo mundo de programação funcional, cheio de es6 +, webpack-dev-server, tdd, eslint, compilação automática e assim por diante.
E aqui no mundo adulto, tudo é completamente diferente ...
Gravata
Mas gosto de trabalhar, considero obstáculos como oportunidades de autodesenvolvimento, a empresa é boa, a atmosfera é excelente, meus olhos estão pegando fogo!
Nas horas de trabalho, realizo tarefas de trabalho, no meu tempo livre tento melhorar alguma coisa.
Em meados de junho, começo com uma tentativa de fixar o webpack, mas a primeira abordagem espera uma falha completa. Estou atormentado há uma semana, estou muito cansado disso, temporariamente adiado.
Eu decido começar pequeno - conecto a nova sintaxe através do babel. Eu adiciono o processamento inicial de babel à nossa build.bat mágica, mas algo quebra o idílio e nosso velho minificador tropeça. Estou procurando um problema.
Tropeça em uma das bibliotecas das boas bibliotecas do papai. Eu olho para os arquivos da biblioteca: eles já estão minificados na sintaxe antiga.
Eu digo babel - "você não vai aqui ... a cabeça vai pegar o código, vai ser muito ruim". Verifico: tudo funciona! Viva! Agora eu tenho acesso a todas essas novas e elegantes coisas da juventude na moda! Primeira vitória. Nice Acho que nesta ocasião renomear o script em e.bat (e-Evgen), mas não consigo decidir.
A nova sintaxe é tão familiar e agradável, mas o pensamento de uma construção torta não me deixa.
O final de junho e o início de julho. Estou fazendo a segunda abordagem, mais minuciosamente, mas, novamente, encontro erros entre o webpack e o angularjs. Novamente uma semana de pesquisa.
Depois de passar vários dias e parcialmente noites à procura de uma solução, deparo-me com discursos extremamente interessantes da conferência HolyJS, onde os caras já estão se aprofundando no webpack. Estou avançando em seu entendimento, mas ainda não entendo o material até o fim.
O interesse se fortalece.
Um colega diz - esqueça, para entregar o projeto em alguns meses, não é mais necessário fazer isso.
Eu não martelo, mas adiei - muito trabalho, isso me aperta tudo, não resta tempo para atividades extracurriculares.
Em meados de julho, chego em minhas mãos semelhante ao nosso projeto com uma compilação personalizada. Vou com ele para a terceira abordagem e praticamente estou configurando o webpack conosco, mas no final estou pegando novos erros que não tenho tempo para resolver, o trabalho rola com nova intensidade + me devasta mentalmente, deixo de lado esse negócio novamente.
Corpo principal
Meados de agosto. Como resultado, um amigo fala sobre o aprendizado do node.js e seu desejo de escrever seu próprio hot-reloader. Pensamentos sobre nossa assembléia surgem com vigor renovado.
Tarefa: recarregar a página atual ao atualizar arquivos no projeto.
Recursos: todas as bibliotecas estão conectadas em index.html, você não pode exigir, para não mencionar a importação. A montagem antes da recarga ainda não é necessária, apenas recarregue. Em um servidor de desenvolvimento que solicita proxies para nosso apoio, eu posso usar pacotes e também posso exigir!
Tudo isso acontece na sexta-feira e eu decido que, em uma versão simplificada do nosso projeto, sou capaz de implementar uma tecnologia que salvará a mim e aos meus colegas da F5.
O processo de pensamento continua e uma visão da solução é formada na cabeça.
O servidor mais simples (como o nosso), contornarei toda a pasta e subpastas e formará uma árvore com as datas de modificação de cada arquivo.
Depois de cada milissegundo, ignorarei repetidamente e compararei os valores do tempo de mudança. Alterado - recarregar. Um amigo diz a você: “não reinvente a roda, há um relógio no node.js”. Ótimo, eu vou usá-lo. No server.js, configurarei o watch behind a pasta do projeto e chamarei location.reload () para alterar algo.
Primeira iteração:
server.jsvar express = require('express'); var app = express(); var server = require('http').Server(app); const port = 9080; server.listen(port); app.use(express.static(__dirname + '/src')); location.reload().
O primeiro problema é location- esta não é uma variável node.js. (neste momento entendo por que minhas tentativas de acessar process.env na frente também não tiveram êxito))).
O segundo problema é como fazer a frente entender o que a recarga precisa fazer.
Saída - websocket! A ideia é tentadora + eu trabalhei com eles “meio-cones” quando escrevi uma conversa, tenho uma ideia geral. Ao mesmo tempo, faço um contador de reinicialização por sessão, adiciono uma variável e processo a solicitação que a fornece.
Eu tento:
server.js var express = require('express'); // express var app = express(); var server = require('http').Server(app); // http app var io = require('socket.io')(server); // socket.io var fs = require('fs'); const port = 9080; server.listen(port); app.use(express.static(__dirname + '/src')); let count = 0; app.get('/data', (req, res) => { res.data = count; res.send(`${count}`); }) const dir = './src'; fs.watch(dir, () => { io.emit('change', {data: count}); count += 1; })
Na frente eu estou fazendo o aplicativo mais simples no angularjs
app.js angular.module('App', []) .controller('myAppCtrl',['$scope', '$timeout','$http', ($scope, $timeout, $http) => { $scope.title = ' '; $scope.count = 0; $scope.todo = [ ' , ', ' node.js watch ', ' , ', ' , codeclimate travis ' ] $scope.marks = [ 'watcher ' ] // var socket = io(); // socket.on('change', (data) => { // console.log(data.data); // $scope.count = data.data; // console.log('scope.count: ', $scope.count); // $scope.$digest();// // location.reload();//agfr // }) $http({method: 'GET',url: 'data'}) .then(response => { $scope.count = response.data;// }); }])
E um módulo separado que o recarrega. Separe, para que o projeto não fique muito.
watch.js var socket = io(); socket.on('change', () => { location.reload(); })
Isso funciona! Ele também monitora outros arquivos que não js (você nunca sabe!): Verificado .json, .css.
Eu verifico as subpastas - não funciona.
Acho que tudo bem, agora vou cortar recursivamente. Apenas no caso, o Google e - voila - está pronto
a decisão.Adicione este pacote.
server.js var express = require('express'); // express var app = express(); var server = require('http').Server(app); // http app var io = require('socket.io')(server); // socket.io var fs = require('fs'); var watch = require('node-watch'); const port = 9080; server.listen(port); app.use(express.static(__dirname + '/src')); let count = 0; let changed = []; app.get('/data', (req, res) => { res.data = count; res.send({count, changed}); }) const translate = { remove: "", update: "" } watch('./', { recursive: true }, function(evt, name) { io.emit('change', {data: count}); count += 1; changed = [{name, evt}, ...changed]; });
Viva, funciona!
Lembro-me de eslint, codeclimate e travis.
Instale o primeiro, adicione o resto.
Eu limpo o código, tudo é var na const e assim por diante.
Linter jura que angular não está definido, mas meus recursos de conexão de bibliotecas no projeto ditam esse comportamento, eu desativo. Ao mesmo tempo, eu estrago um pouco as variáveis da linha de comando, corro tudo funcionando!
Ele veio trabalhar na segunda-feira e prendeu a fazenda inteira a um esboço de trabalho. Eu tive que mudar um pouco, ao mesmo tempo, fazer alterações para que fosse possível alterar alguns parâmetros de inicialização na linha de comando e exceções, para não ler tudo.
Como resultado, ficou assim:
server.js const express = require('express'), http = require('http'), watch = require('node-watch'), proxy = require('http-proxy-middleware'), app = express(), server = http.createServer(app), io = require('socket.io').listen(server), exeptions = ['git', 'js_babeled', 'node_modules', 'build', 'hotreload'], // , , backPortObj = { /* , back*/ }, address = process.argv[2] || /* back*/, localHostPort = process.argv[3] || 9080, backMachinePort = backPortObj[address] || /* back */, isHotReload = process.argv[4] || "y", // "n" || "y" target = `http://192.168.${address}:${backMachinePort}`, str = `Connected to machine: ${target}, hot reload: ${isHotReload === 'y' ? 'enabled' : 'disabled'}.`, link = `http://localhost:${localHostPort}/`; server.listen(localHostPort); app .use('/bg-portal', proxy({ target, changeOrigin: true, ws: true })) .use(express.static('.')); if (isHotReload === 'y') { watch('./', { recursive: true }, (evt, name) => { let include = false; exeptions.forEach(item => { if (`${name}`.includes(item)) include = true; }) if (!include) { console.log(name); io.emit('change', { evt, name, exeptions }); }; }); }; console.log(str); console.log(link);
app.js var socket = io.connect(); socket.on('change', ({ evt, name, exeptions }) => { location.reload(); });
o script em execução no package.json apenas chama server.js no nó e ele começa assim:
npm start 1.100 8080
Escreveu. Salvo.
F5Concluindo, quero agradecer a Vanya, minha amiga, em alguns lugares, o mentor e o kicker principal, bem como Sasha - o homem a quem considero meu mentor!
Em vez de um posfácio
Depois de duas semanas, no último dia do meu período de teste, apertei o webpack e o webpack-dev-server em nosso projeto, enviando meu recarregador quente para o pó na prateleira do histórico.
No entanto, nessas duas semanas nós o usamos todos os dias e ele fazia seu trabalho regularmente!