После прочтения ряда статей (например, этой) решил перейти на современный подход с использованием Node.js при написании простых сайтов с подхода «динозавров». Ниже представлен разбор примера сборки простого статического сайта с помощью Webpack 4. Статья написана, так как инструкции с решением моей задачи не нашел: пришлось собирать всё по кусочкам.
Постановка задачи
Сайт представляет собой простой набор HTML-страниц со своим CSS стилями и файлом JavaScript. Необходимо написать проект, который бы собирал наш сайт из исходников:
- из SASS (точнее SCSS) файлов формируется один CSS файл;
- из различных JavaScript библиотек и пользовательского кода формируется один JavaScript файл;
- HTML страницы собираются с помощью шаблонизатора, где содержимое шапки и футера можно разнести по отдельным файлам.
В собранном сайте не должны использоваться React, Vue.js.
При выборе технологий выбираются по возможности наиболее популярные на данный момент. По этой причине отказался и от Grunt и Gulp в пользу Webpack, хотя, если честно, синтаксис Gulp мне понравился больше своим однообразием.
Для примера будет сверстано несколько страничек на базе Bootstrap 4. Но это только для примера.
Предполагается, что Node.js установлен (в Windows просто скачивается установщик и устанавливается в стиле «далее, далее»), и вы умеете работать с командной строкой.
Структура проекта
Общая структура проекта представлена ниже:
.
+-- dist - папка, куда будет собираться сайт
+-T src - папка с исходниками сайта
¦ +-- favicon - папка с файлами иконок для сайта
¦ +-- fonts - папка со шрифтами
¦ +-T html - папка заготовок HTML страниц
¦ ¦ +-- includes - папка с встраиваемыми шаблонами (header, footer)
¦ ¦ L-- views - папка с самими HTML страницами
¦ +-- img - папка с общими изображениями (логотип, иконки и др.)
¦ +-- js - папка с JavaScript файлами
¦ +-- scss - папка с SСSS файлами
¦ L-- uploads - папка с файлами статей (картинки, архивы и др.)
+-- package.json - файл настроек Node.js
L-- webpack.config.js - файл настроек Webpack
.
+-- dist
+-T src
¦ +-T favicon
¦ ¦ L-- favicon.ico
¦ +-T fonts
¦ ¦ L-- Roboto-Regular.ttf
¦ +-T html
¦ ¦ +-T includes
¦ ¦ ¦ +-- footer.html
¦ ¦ ¦ L-- header.html
¦ ¦ L-T views
¦ ¦ +-- index.html
¦ ¦ L-- second.html
¦ +-T img
¦ ¦ L-- logo.svg
¦ +-T js
¦ ¦ L-- index.js
¦ +-T scss
¦ ¦ L-- style.scss
¦ L-T uploads
¦ L-- test.jpg
+-- package.json
L-- webpack.config.js
Под favicon выделена целая папка, так как в современном web обычным одним ico файлом не обойтись. Но для примера используется только этот один файл.
Спорным решением может показаться разделение картинок на две папки: img
и uploads
. Но здесь использовал идеологию расположения файлов из Wordpress. На мой взгляд, кидать все изображения в одну папку — не очень хорошая идея.
Для работы с проектом использую Visual Studio Code, которым очень доволен. Особенно мне нравится, что командная строка встроена в программу и вызывается через Ctrl + `.
Сделаем болванку Node.js проекта. Для этого создадим папку нашего проекта с вышеописанной структурой и перейдем в неё в командной строке, где вызовем команду для создания файла package.json
.
npm init
На все вопросы можно просто отвечать, нажимая Enter
, если заполнять подробную информацию не хочется.
Установим три общих пакета, которые нам потребуются в любом случае: webpack
, webpack-cli
(работу с командной строкой в webpack вынесли в отдельный пакет) и webpack-dev-server
(для запуска локального сервера, чтобы в браузере сразу отображались сохраненные изменения проекта).
npm install webpack webpack-cli webpack-dev-server --save-dev
{
"name": "static-site-webpack-habrahabr",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"license": "ISC",
"devDependencies": {
"webpack": "^4.1.1",
"webpack-cli": "^2.0.11",
"webpack-dev-server": "^3.1.1"
}
}
Также создастся файл package-lock.json
, который вообще не трогаем. Но в git репозиторий добавлять этот файл нужно, в отличии от папки node_modules
, которую нужно прописать в файле .gitignore
, если пользуетесь git.
Собираем JavaScript
Так как Webpack создан в первую очередь для сборки js файлов, то эта часть будем самой простой. Чтобы можно было писать javascript в современном виде ES2015, который не поддерживается браузерами, поставим пакеты babel-core
, babel-loader
, babel-preset-env
.
npm install babel-core babel-loader babel-preset-env --save-dev
После создаем файл настроек webpack.config.js
с таким содержимым:
const path = require('path');
module.exports = {
entry: [
'./src/js/index.js',
],
output: {
filename: './js/bundle.js'
},
devtool: "source-map",
module: {
rules: [{
test: /\.js$/,
include: path.resolve(__dirname, 'src/js'),
use: {
loader: 'babel-loader',
options: {
presets: 'env'
}
}
},
]
},
plugins: [
]
};
В разделе entry
(точки входа) указываем, какой js файл будем собирать, в разделе output
указываем путь в папке dist
, куда будем помещаться собранный файл. Обратите внимание, что в webpack 4 в пути output
саму папку dist
указывать не нужно! И да, как же мне не нравится, что в одном файле webpack в одних случаях нужно писать относительный путь, в других случаях относительный путь в специальной папке, в третьих случаях нужен уже абсолютный путь (например, его получаем этой командой path.resolve(__dirname, 'src/js')
).
Также указано значение параметра devtool
, равное: source-map
, что позволит создавать карты исходников для js и css файлов.
Для обработки конкретных файлов (по расширению, по месторасположению) в webpack создаются правила в разделе rules
. Сейчас у нас там стоит правило, что все js файлы пропускаем через транслятор Babel, который преобразует наш новомодный ES2015 в стандартный javascript вариант, понятный браузерам.
В нашем тестовом примере мы верстаем наши странице на Boostrap 4. Поэтому нам нужно будет установить три пакета: bootstrap
, jquery
, popper.js
. Второй и третий пакет мы устанавливаем по требованию Bootstrap.
npm install bootstrap jquery popper.js --save
Обратите внимание на то, что эти три пакета нам нужны именно для самого сайта, а не для его сборки. Поэтому эти пакеты мы устанавливаем с флагом --save
, а не --save-dev
.
Теперь можно приступить к написанию нашего index.js
файла:
import jQuery from 'jquery';
import popper from 'popper.js';
import bootstrap from 'bootstrap';
jQuery(function() {
jQuery('body').css('color', 'blue');
});
В качестве примера пользовательского кода js просто перекрасили цвет текста на синий.
Теперь можно перейти к сборке js файла. Для этого в файле package.json
в разделе scripts
пропишем следующие npm скрипты:
"scripts": {
"dev": "webpack --mode development",
"build": "webpack --mode production",
"watch": "webpack --mode development --watch",
"start": "webpack-dev-server --mode development --open"
},
Теперь при запуске в командной строке строчки npm run dev произойдет сборка проекта (css и html файлы потом также будут собираться этой командой), и в папке /dist/js
появятся файлы bundle.js
и bundle.js.map
.
При запуске команды npm run build также произойдет сборка проекта, но уже итоговая (с оптимизацией, максимальной минимизацией файла), которую можно выкладывать на хостинг.
При запуске npm run watch запускается режим автоматического просмотра изменений файлов проекта с автоматическим допостроением измененных файлов. Да, чтобы в командной строке отключить этот режим (например, чтобы можно было написать другие команды) можно нажать Ctrl + C
(как минимум в PowerShell).
При запуске npm run start запустится локальный сервер, который запустит html страницу и также будет отслеживать изменения в файлах. Но пока этой командой не пользуемся, так как сборку html страниц не добавили.
Режим построения проекта создает или переписывает файлы в папке dist
. Но во время разработки проекта при разных сборках файлы могут переименовываться, удаляться. И Webpack не будет следить, чтобы уже ненужные файлы, оставшиеся после предыдущих сборок, удалялись из папки dist
. Поэтому добавим еще один пакет clean-webpack-plugin
, который будет очищать папку dist
перед каждой сборкой проекта.
npm install clean-webpack-plugin --save-dev
Внесем изменения в файл webpack.config.js
.
...
const CleanWebpackPlugin = require('clean-webpack-plugin')
module.exports = {
...
plugins: [
new CleanWebpackPlugin(['dist']),
]
};
Сборка CSS файла
CSS файл будем собирать из SCSS файлов, под которые у нас зарезервирована папка src/scss
. В ней создадим файл style.scss
, например, со следующим содержимым:
$font-stack: -apple-system, BlinkMacSystemFont,Roboto,'Open Sans','Helvetica Neue',sans-serif;
@import "~bootstrap/scss/bootstrap";
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 400;
src: url(../fonts/Roboto-Regular.ttf);
}
body {
font-family: $font-stack;
#logo {
width: 10rem;
}
.container {
img {
width: 20rem;
}
}
}
Обратите внимание на то, что стили Bootstrap подключаем не через его CSS файл, а через SСSS (@import "node_modules/bootstrap/scss/bootstrap"
@import "~bootstrap/scss/bootstrap";
), который позволит в случае надобности переписать те или иные свойства библиотеки, использовать его миксины и др. Но что печалит. Если при сборке js файла при подключении js файла Bootstrap библиотеки Webpack знает, где находятся нужные файлы, то при подключении стилей нужно указывать путь к папке в node_modules
.
Для обработки css файлов нам будут нужны следующие модули: node-sass
, sass-loader
, css-loader
и extract-text-webpack-plugin
(говорят, что в следующей версии Webpack в последнем плагине надобность отпадет).
Важно! На момент написания статьи плагин extract-text-webpack-plugin
в стабильной версии не умеет работать с Webpack 4. Поэтому нужно устанавливать его beta версию через @next
:
npm install node-sass sass-loader css-loader extract-text-webpack-plugin@next --save-dev
Надеюсь, что вскоре можно будет устанавливать все плагины по нормальному:
npm install node-sass sass-loader css-loader extract-text-webpack-plugin --save-dev
В webpack.config.js
добавим следующие изменения:
...
const ExtractTextPlugin = require("extract-text-webpack-plugin");
...
module.exports = {
entry: [
...
'./src/scss/style.scss'
],
...
module: {
rules: [{
...
{
test: /\.(sass|scss)$/,
include: path.resolve(__dirname, 'src/scss'),
use: ExtractTextPlugin.extract({
use: [{
loader: "css-loader",
options: {
sourceMap: true,
minimize: true,
url: false
}
},
{
loader: "sass-loader",
options: {
sourceMap: true
}
}
]
})
},
]
},
plugins: [
new ExtractTextPlugin({
filename: './css/style.bundle.css',
allChunks: true,
}),
...
]
};
Обратите внимание на то, что в точках входа entry
мы добавили новый входной файл style.scss
, но выходной файл указали не в output
, а в вызове плагина ExtractTextPlugin в разделе plugins
. Включаем поддержку карт источников sourceMap для пакетов sass-loader
и css-loader
.
Также можно заметить, что тут нет пакета style-loader
, который чаще всего упоминается при работе с css в Webpack. Данный пакет встраивает css код в файл HTML, что может быть удобно для одностраничных приложений, но никак не для многостраничного.
И самый спорный момент. Для пакета css-loader
мы добавили параметр url
, равный false
. Зачем? По умолчанию url=true
, и если Webpack при сборке css находит ссылки на внешние файлы: фоновые изображения, шрифты (например, в нашем случае есть ссылка на файл шрифта url(../fonts/Roboto-Regular.ttf)
), то он эти файлы попросит как-то обработать. Для этого используют чаще всего пакеты file-loader
(копирует файлы в папку сборки) или url-loader
(маленькие файлы пытается встроить в HTML код). При этом прописанные относительные пути к файлам в собранном css могут быть изменены.
Но с какой проблемой столкнулся на практике. Есть у меня папка src/scss
с SСSS кодом. Есть папка src/img
с картинками, на которые ссылаются в SСSS коде. Всё хорошо. Но, например, мне потребовалось подключить на сайт стороннюю библиотеку (например, lightgallery). SCSS код у неё располагается в папке node_modules/lightgallery/src/sass
, который ссылается на картинки из папки node_modules/lightgallery/src/img
через относительные пути. И если добавить стили библиотеки в наш style.scss
, то file-loader
будет искать картинки библиотеки lightgallery
в моей папке src/img
, а не там, где они находятся. И побороть я это не смог.
Поэтому установкой url=false
говорим, что все ссылки на файлы в SCSS коде не трогаем, пути не меняем, никакие файлы не копируем и не встраиваем: с ними разберемся потом отдельно. Возможно, это решение плохое, и вы предложите более правильный подход.
Сборка HTML страниц
Перейдем к самому веселому: к сборке HTML страниц, где у меня возникли самые большие трудности.
Для сборки HTML страниц будем использовать плагин html-webpack-plugin
, который поддерживает различные виды шаблонизаторов. Также нам потребуются пакет raw-loader
.
npm install html-webpack-plugin raw-loader --save-dev
В качестве шаблонизатора HTML будем использовать шаблонизатор по умолчанию lodash. Вот так будет выглядеть типичная HTML страница до сборки:
<% var data = {
title: "Заголовок | Проект",
author: "Harrix"
}; %>
<%= _.template(require('./../includes/header.html'))(data) %>
<p>text</p>
<%= _.template(require('./../includes/footer.html'))(data) %>
Вначале в переменной data
прописываем все наши переменные страницы, которые хотим использовать на этой странице. Потом встраиваем шаблоны шапки и футера через _.template(require())
.
Важное уточнение. В статьях про сборку HTML страниц через html-webpack-plugin
обычно подключают встраиваемые шаблоны просто через команду:
require('html-loader!./../includes/header.html')
Но при этом в этих встраиваемых шаблонах синтаксис lodash работать не будет (я так и не понял, почему так происходит). И данные из переменной data
туда не передадутся. Поэтому принудительно говорим webpack, что мы встраиваем именно шаблон, который надо обработать как lodash шаблон.
Теперь мы можем использовать полноценные lodash синтаксис в встраиваемых шаблонах. В коде файла header.html
ниже через <%=title%>
печатаем заголовок статьи.
<!doctype html>
<html lang="ru">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="shortcut icon" href="favicon/favicon.ico">
<link rel="stylesheet" href="css/style.bundle.css">
<title><%=title%></title>
</head>
<body>
<header><img src="img/logo.svg" id="logo"></header>
В пакете html-webpack-plugin есть возможность генерировать несколько HTML страниц:
plugins: [
new HtmlWebpackPlugin(), // Generates default index.html
new HtmlWebpackPlugin({ // Also generate a test.html
filename: 'test.html',
template: 'src/assets/test.html'
})
]
Но прописывать для каждой страницы создание своего экземпляра плагина точно не есть хорошо. Поэтому автоматизируем этот процесс, найдя все HTML файлы в папке src/html/views
и создадим для них свои версии new HtmlWebpackPlugin()
.
Для этого в файле webpack.config.js
внесем следующие изменения:
...
const HtmlWebpackPlugin = require('html-webpack-plugin');
const fs = require('fs')
function generateHtmlPlugins(templateDir) {
const templateFiles = fs.readdirSync(path.resolve(__dirname, templateDir));
return templateFiles.map(item => {
const parts = item.split('.');
const name = parts[0];
const extension = parts[1];
return new HtmlWebpackPlugin({
filename: `${name}.html`,
template: path.resolve(__dirname, `${templateDir}/${name}.${extension}`),
inject: false,
})
})
}
const htmlPlugins = generateHtmlPlugins('./src/html/views')
module.exports = {
module: {
...
{
test: /\.html$/,
include: path.resolve(__dirname, 'src/html/includes'),
use: ['raw-loader']
},
]
},
plugins: [
...
].concat(htmlPlugins)
};
Функция generateHtmlPlugins
будет осуществлять поиск всех HTML страниц. Обратите внимание, что в коде функции есть настройка inject: false
, которая говорит Webpack, что не нужно встраивать ссылки на js и css файл в HTML код самостоятельно: мы сделаем всё сами вручную в шаблонах header.html
и footer.html
.
Также нужно отметить, что встраиваемые шаблоны обрабатываются плагином raw-loader
(содержимое файла просто загрузить как текст), а не html-loader
, как чаще всего предлагают. И также, как в случае с CSS, не использую пакеты file-loader
или url-loader
.
И остается последний необязательный момент для работы с HTML. JavaScript файл и CSS файл у нас будут минимифицроваться. А вот HTML файлы хочу, наоборот, сделать красивыми и не минифицировать. Поэтому после сборки всех HTML файлов хочется пройтись по ним каким-то beautify плагином. И тут меня ждала подстава: не нашел способа как это сделать в Webpack. Проблема в том, что обработать файлы нужно после того, как будут вставлены встраиваемые шаблоны.
Нашел пакет html-cli, который может это сделать независимо от Webpack. Но у него 38 установок в месяц. То есть это означает два варианта: либо никому не нужно приводить к красивому внешнему виду HTML файлы, либо есть другое популярное решение, о котором я не знаю. А ради только одной этой функции Gulp прикручивать не хочется.
Устанавливаем этот плагин:
npm install html-cli --save-dev
И в файле package.json
прописываем еще два скрипта, которые после работы Webpack будут приводить к красивому внешнему виду HTML файлы с установкой табуляции в два пробела.
"scripts": {
"build-and-beautify": "webpack --mode production && html dist/*.html --indent-size 2",
"beautify": "html dist/*.html --indent-size 2"
},
Поэтому для итоговой сборки рекомендую использовать не команду *npm run build, а команду npm run build-and-beautify.
Копирование оставшихся файлов
Мы сгенерировали js, css файлы, HTML страницы. Остались файлы изображений, шрифтов и др., которые мы не трогали и сознательно не копировали через file-loader
или url-loader
. Поэтому скопируем все оставшиеся папки через плагин copy-webpack-plugin
:
npm install copy-webpack-plugin --save-dev
В файле webpack.config.js
внесем изменения:
...
const HtmlWebpackPlugin = require('html-webpack-plugin');
...
module.exports = {
...
plugins: [
...
new CopyWebpackPlugin([{
from: './src/fonts',
to: './fonts'
},
{
from: './src/favicon',
to: './favicon'
},
{
from: './src/img',
to: './img'
},
{
from: './src/uploads',
to: './uploads'
}
]),
]...
};
Всё. Теперь командой npm run build-and-beautify собираем проект и в папке dist
появится собранный статический сайт.
Итоговые файлы
{
"name": "static-site-webpack-habrahabr",
"version": "1.0.0",
"description": "HTML template",
"main": "src/index.js",
"scripts": {
"dev": "webpack --mode development",
"build": "webpack --mode production",
"build-and-beautify": "webpack --mode production && html dist/*.html --indent-size 2",
"watch": "webpack --mode development --watch",
"start": "webpack-dev-server --mode development --open",
"beautify": "html dist/*.html --indent-size 2"
},
"dependencies": {
"bootstrap": "^4.0.0",
"jquery": "^3.3.1",
"popper.js": "^1.13.0"
},
"devDependencies": {
"babel-core": "^6.26.0",
"babel-loader": "^7.1.3",
"babel-preset-env": "^1.6.1",
"clean-webpack-plugin": "^0.1.18",
"copy-webpack-plugin": "^4.5.0",
"css-loader": "^0.28.9",
"extract-text-webpack-plugin": "^4.0.0-beta.0",
"html-cli": "^1.0.0",
"html-webpack-plugin": "^3.0.4",
"node-sass": "^4.7.2",
"raw-loader": "^0.5.1",
"sass-loader": "^6.0.6",
"webpack": "^4.0.1",
"webpack-cli": "^2.0.10",
"webpack-dev-server": "^3.1.0"
}
}
const path = require('path');
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const CopyWebpackPlugin = require('copy-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin')
const fs = require('fs')
function generateHtmlPlugins(templateDir) {
const templateFiles = fs.readdirSync(path.resolve(__dirname, templateDir));
return templateFiles.map(item => {
const parts = item.split('.');
const name = parts[0];
const extension = parts[1];
return new HtmlWebpackPlugin({
filename: `${name}.html`,
template: path.resolve(__dirname, `${templateDir}/${name}.${extension}`),
inject: false,
})
})
}
const htmlPlugins = generateHtmlPlugins('./src/html/views')
module.exports = {
entry: [
'./src/js/index.js',
'./src/scss/style.scss'
],
output: {
filename: './js/bundle.js'
},
devtool: "source-map",
module: {
rules: [{
test: /\.js$/,
include: path.resolve(__dirname, 'src/js'),
use: {
loader: 'babel-loader',
options: {
presets: 'env'
}
}
},
{
test: /\.(sass|scss)$/,
include: path.resolve(__dirname, 'src/scss'),
use: ExtractTextPlugin.extract({
use: [{
loader: "css-loader",
options: {
sourceMap: true,
minimize: true,
url: false
}
},
{
loader: "sass-loader",
options: {
sourceMap: true
}
}
]
})
},
{
test: /\.html$/,
include: path.resolve(__dirname, 'src/html/includes'),
use: ['raw-loader']
},
]
},
plugins: [
new ExtractTextPlugin({
filename: './css/style.bundle.css',
allChunks: true,
}),
new CleanWebpackPlugin(['dist']),
new CopyWebpackPlugin([{
from: './src/fonts',
to: './fonts'
},
{
from: './src/favicon',
to: './favicon'
},
{
from: './src/img',
to: './img'
},
{
from: './src/uploads',
to: './uploads'
}
]),
].concat(htmlPlugins)
};
<% var data = {
title: "Заголовок | Проект",
author: "Harrix"
}; %>
<%= _.template(require('./../includes/header.html'))(data) %>
<div class="container">
<p>Первая страница.</p>
<p><img src="uploads/test.jpg"></p>
</div>
<%= _.template(require('./../includes/footer.html'))(data) %>
<!doctype html>
<html lang="ru">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="shortcut icon" href="favicon/favicon.ico">
<link rel="stylesheet" href="css/style.bundle.css">
<title><%=title%></title>
</head>
<body>
<header><img src="img/logo.svg" id="logo"></header>
<footer><%=author%></footer>
<script src="js/bundle.js"></script>
</body>
</html>
<!doctype html>
<html lang="ru">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="shortcut icon" href="favicon/favicon.ico">
<link rel="stylesheet" href="css/style.bundle.css">
<title>Заголовок | Проект</title>
</head>
<body>
<header><img src="img/logo.svg" id="logo"></header>
<div class="container">
<p>Первая страница.</p>
<p><img src="uploads/test.jpg"></p>
</div>
<footer>Harrix</footer>
<script src="js/bundle.js"></script>
</body>
</html>
Исходники
Ссылка на репозиторий с рассмотренным проектом.
Комментарии (65)
SevenLines
13.03.2018 12:06А использовались ли какие-нибудь фичи нового webpack? А то по названию как будто упор на 4 версию идёт. А с виду тот же третий.
Harrix Автор
13.03.2018 17:16Как уже отметили, режимы
--mode development
и--mode production
. Также отсутствие необходимости указывать пакуdist
в путях в файлеwebpack.config.js
. А также отсутствие некоторых плагинов (это скорее антифича). Например, jshint пока прикрутить нельзя, так как jshint-loader не работает с новым Webpack.SevenLines
13.03.2018 17:52eplaksin, Harrix, спасибо.
Тут недавно статья была про новый вебпак, и как там все здорово будет. А по сути изменения получаются скорее косметические. Я то думал что будет какой-то режим сборки из коробки, без возни с конфигами, но его нет. И в результате, по моим личным ощущениям, получается, что использовать webpack что 3-ий, что 4-ый, для сбора статического сайта это все таки небольшой оверхед.Harrix Автор
13.03.2018 17:57Режим для сборки из коробки там есть. Но как показывает практика, всегда будут появляться свои хотелки, которые потребуют написание своих конфигов.
Разумеется, для полноценного статического сайта куда лучше подойдет специализированный инструмент, как тот же Jekyll. Но и там те же css и js надо будет кем-то собирать. И тогда появляется связка Jekyll + webpack или Jekyll + gulp. Вот и решил для простых вариантов обойтись одним инструментом.
sinneren
13.03.2018 12:26`new CleanWebpackPlugin(['dist', 'build']),`
зачем build здесь, ведь эта папка не фигурирует нигде. Потом, столько мусора, в bundle.js есть пути до scss. Зачем…Harrix Автор
13.03.2018 17:28Ошибку с CleanWebpackPlugin поправил. Спасибо!
А вот про мусор не понял. В bundle.js нет упоминаний про scss. А вы как собирали проект? Черезnpm run
dev илиnpm run build
? В первом случае bundle.js будет содержать много мусорного, так как сборка происходит в режиме разработки.
PaulZi
13.03.2018 14:17+1Но что печалит. Если при сборке js файла при подключении js файла Bootstrap библиотеки Webpack знает, где находятся нужные файлы, то при подключении стилей нужно указывать путь к папке в node_modules.
Можно писать так:
@import "~bootstrap/scss/bootstrap";
по крайней мере node_modules не надо писать. Путь внутри пакета конечно придётся писать, т. к. в package.json пакета нет ключа "main" для стилей.
DexterHD
13.03.2018 14:38После прочтения ряда статей (например, этой) решил перейти на современный подход с использованием Node.js при написании простых сайтов с подхода «динозавров».
Это сарказм?? Перед вами бизнес (вы сами) поставил простейшую задачу:
Сайт представляет собой простой набор HTML-страниц со своим CSS стилями и файлом JavaScript
Ваш репозиторий с установленными зависимостями весит 177 MB..
Война и Мир в HTML будет весить не более 20 Мб. 2300 зависимостей!
Вот дерево зависимостей которые вы для этого подтянули, оно не умещается в комментарий:
gist.github.com/DexterHD/9ed32eedf9412e7c1fdfaf6a1c458fae
И это все чтобы создать набор из HTML страниц с несколькими CSS и JS??? Серьезно Современный подход??tbopec
13.03.2018 16:33Скомпилированные js, css весят 155 KB и 118 KB соответственно.
Некомпилированные js, scss, шаблоны — несколько килобайт.
Все остальное — использованные библиотеки, плюс «компиляторы» и тп. Считать их размер в размер репозитория некорректно.
К примеру, в .Net вы тоже считаете вес всего фреймворка, .Net компиляторов — это же тоже зависимости? Затем зависимости следующего уровня — API операционной системы, в общем операционную систему, компилятор в машинные команды, ещё кучи библиотек.
Harrix Автор
13.03.2018 17:44В реальности собирается чуть посложнее сайт, но да. Современный подход, к сожалению или к счастью, выглядит так. От количества файлов в node_modules у самого глаза на лоб лезут. А пока собирал проект по кусочкам — обматерил всех и вся. Но, представьте, что папки node_modules нет. И она заменена на обычное приложение, которое весит все те же 177 Мб и выполняет тоже самое. В этом случае такой жесткой критики не будет.
А по правде говоря меня очень даже устраивала определенное время Koala для решения задачи сборки CSS из SASS и минификации js файлов. Но потом появились хотелки, которые она уже не могла решать (та же шаблонизация HTML). Вот и появился повод разобраться в «современном подходе». Но я уверен, что в ближайшие годы многое изменится.redfs
13.03.2018 20:21Современный подход, к сожалению или к счастью, выглядит так
Вы ошибаетесь. Подход сам по себе не может быть «современным» или «олдовым». Любой подход определяется выбором правильного инструмента для реализации. Вы выбрали современный инструмент, но это вовсе не значит, что этот инструмент обеспечил правильный подход и правильное/оптимальное решение вашей задачи.Harrix Автор
13.03.2018 20:44Подход сам по себе не может быть «современным» или «олдовым».
Вы выбрали современный инструмент
Вы сами себе противоречите. Есть современные и есть олдовые подходы. А то, что современный подход является оптимальным решением — я этого нигде не говорил. Например, серьезный статический сайт, на подобии Jekyll не написать (хотя для таких задач я предпочту динамический сайт, но это тема другого холивара). А сам webpack мне очень многим не нравится. И я уверен, что на смену ему придет что-то другое.redfs
13.03.2018 21:52Вы сами себе противоречите… А то, что современный подход является оптимальным решением — я этого нигде не говорил.
Вроде нет противоречия. Поясню. Я исхожу от задачи, озвученной вами в статье. Задача решена, но плохо, хоть и современными методами.
Если бы ваша постановка задачи выглядела как-то так:
Задача (цель): Изучить современные технологии (webpack)
Способ решения: Собрать простой статический сайт с помощью webpack 4.
то можно было бы сказать, что задача решена хорошо.Harrix Автор
13.03.2018 21:58Почему решение задачи плохое? И какое решение, на ваш взгляд, хорошее?
redfs
15.03.2018 06:25Почему решение задачи плохое?
Как вы сами признали, оно не является оптимальным. Почти по всем параметрам — время на разработку, пара тысяч зависимостей (в курсе истории о том, что было, когда одна из зависимостей сломалась и пропала из репо?), дальнейшее сопровождение и т.д. и т.п. Иными словами — вы простейшую, можно сказать — тестовую задачу решали, создавая себе максимальные сложности.
Однако опять отмечу, что если вы все-таки решали другую задачу (самообучение), то задача решена хорошо.
К сожалению, сейчас повсеместная беда с постановкой задачи, как таковой. Люди путают цели со средствами их достижения.
И какое решение, на ваш взгляд, хорошее?
Понимаете, как штука… Думаю, что это риторический вопрос с вашей стороны, потому что во первых, в комментах уже писали как минимум о нескольких, во вторых, стараюсь не участвовать в религиозных спорах.
Ну как пример, вы пишите о подключаемых хедере и футере, что код шапки прописывать вручную в тысячах файлов — это ад…
Могу сказать, что технология SSI известна больше 20 лет, но наверняка нарвусь на обвинение в «подходе динозавра».Harrix Автор
15.03.2018 08:29Мда… Ожидал нормальная аргументацию.
Как вы сами признали, оно не является оптимальным.
Вы часто говорите странные вещи. То говорите, что я ошибаюсь в том, что существуют современные и олдовые подходы, то потом сами говорите про современные инструменты и подходы динозавров. То теперь сравниваете плохое решение и не оптимальное. Это не одно и тоже!
время на разработку
По вашему любое решение с высоким порогом вхождения — это плохое решение?
пара тысяч зависимостей (в курсе истории о том, что было, когда одна из зависимостей сломалась и пропала из репо?), дальнейшее сопровождение
Есть такой файл. Называется package-lock.json, который хранит подробную информацию о всех пакетах с конкретными номерами версий. Так что я всегда, пока существует npm, смогу получить свой набор пакетов конкретных версий. Но даже если что-то пропадет, то мне достаточно заархивировать папочку node_modules и вообще беспокоиться не о чем.
А если произойдет какой-то капец в пакетах с многомиллионными загрузками, то проблема будет решена очень быстро.
К сожалению, сейчас повсеместная беда с постановкой задачи, как таковой. Люди путают цели со средствами их достижения.
И вот опять. «Цель — конечный результат, на который преднамеренно направлен процесс». В постановке не описаны конкретные инструменты, но они там могли быть на законных основаниях.
в комментах уже писали как минимум о нескольких, во вторых, стараюсь не участвовать в религиозных спорах.
Не надо сливаться. Мне нужен инструмент, который собирал бы HTML страницы, CSS собирал из SASS, Javascript собирал в один файл (желательно с поддержкой модулей), все это минифицировал, находил ошибки, шаблонизаторы HTML поддерживали условия (например, в шапке в меню можно было бы к пунктам меню ставить параметр active в зависимости от имени html страницы), желательно имелся быстрый способ обновления всех библиотек до последних версий и сборка на лету в статический(!) вариант, который мог бы работать локально. Предложите вариант.
Вроде бы насчитал три варианта, которые предлагали на замену. Один с сервером (не подходит под задачу создания статического сайта), один просто с блокнотом (так как я раньше так и делал, то вижу чем это плохо), один с использованием другого пакета из npm (этот вариант может быть даже очень хорошим), который обладает всеми теми же недостатками, которые вы приписали к моему варианту: высокий порог вхождения, зависимости и др.
Могу сказать, что технология SSI известна больше 20 лет
Server Side Includes — зачем вы предлагаете инструмент динамического сайта для статического сайта? Вы это серьезно? Нужна будет динамика — я возьму php или другой язык, куда лучше подходящий, чем SSI. Прочитайте название статьи. Требуется инструмент создания статического(!) сайта!redfs
15.03.2018 08:41Server Side Includes — зачем вы предлагаете инструмент динамического сайта для статического сайта? Вы это серьезно? Нужна будет динамика
Дальнейшие обсуждения не имеют смысла. Динамического? Нет, серьезно? Т.е. вы на самом деле считаете. что статику нельзя подключать через SSI? Знаете, прежде чем следовать моде, неплохо бы с основами разобраться.Harrix Автор
15.03.2018 08:47неплохо бы с основами разобраться.
Это какие-то старые основы. Пока я нахожу статьи 2011 или 2012 года, где рассказывается как SSI использовать на Apache. И статей как-то маловато. Тогда подскажите, пожалуйста, мне недалекому, который основ не знает, как с помощью SSI сгенерировать статические html файлы.redfs
15.03.2018 09:10подскажите, пожалуйста, мне недалекому, который основ не знает, как с помощью SSI сгенерировать статические html файлы
SSI не генерирует статические html файлы, а позволяет делать вставки в статические html файлы. Например, создаете статические header.html и footer.html. Потом можете создавать сколько угодно статических html файлов примерно следующего содержания:
<!--#include file="header.html" --> <p>Моя статическая страница</p> <!--#include file="footer.html" -->
Harrix Автор
15.03.2018 09:20SSI не генерирует статические html файлы
Если он не генерирует статические html страницы, то зачем мне он нужен? Правильно ли я понимаю, что есть сервер, который динамически подгружает include в html страницы по запросу пользователя? Так я про это и говорил, когда сказал «зачем вы предлагаете инструмент динамического сайта», а вы мне обвинили, что я основы не знаю. Сайт получается динамический!!! Ему нужен сервер для генерирования HTML страниц! Или я что-то не понимаю, и всё-таки можно его попросить сгенерировать как-то конкретные статические конечные html файлы.
Мне нужен инструмент статического(!) сайта! Чтобы я на выходе получил набор html файлов, которые я могу закинуть на тот же GitHub Pages или вообще открыть локально на компьютере. SSI для этого не подходит! Статический сайт! Не динамический!
В динамическом сайте HTML страницы генерируются по запросу пользователя на лету из исходников. И не важно являются ли исходники статическими файлами или нет!
В статическом сайте HTML страницы генерируются заранее, и на хостинге хранятся уже сгенерированные HTML страницы!redfs
15.03.2018 11:29Чтобы я на выходе получил набор html файлов, которые я могу… открыть локально на компьютере
Если без сервера, то (навскидку) я бы написал однострочник на bash минут за несколько. Это вообще не проблема — сгенерировать такие файлы.Harrix Автор
15.03.2018 17:14То есть вы назвали решение плохим, не вникнув даже в постановку задачи, и перепутали динамический сайт со статическим. Понятно.
я бы написал однострочник на bash минут за несколько
Это будет точно однострочник? Напишите. И это будет именно настоящий однострочник, а не липовый, когда строчка длинная-предлинная? У меня код, который это делает в проекте, занимает чуть больше десяти строк. Но это уже несерьезно.
И да, даже если вы напишите скрипт на bash, то что изменится? Да, написать программу, которая заменяет содержимое некоторых строчек на содержимое других файлов во всех файлах папки — это легко везде. Только не понимаю, почему это делает мой вариант плохим.
Плюс к этому потом я предложу усложнить задачу: в меню шапки пункты меню, которые соответствуют названию файлов, должны иметь класс acitive. Или еще что-то. В моем решении в lodash шаблоне можно использовать любой js код.
Но даже, если вы покажите вариант (чего наверно не будет), когда bash осуществляет сборку html файлов, то это ничего не поменяет. Так как остаются задачи работы с SASS и js файлами. Сборка, минификация и др. Это как вы предлагаете сделать? Использовать другие инструменты? И завести целый зоопарк технологий? Или что-то другое?justboris
15.03.2018 18:40Вот есть вариант, если что: https://github.com/kidwm/node-ssi
В принципе, идея SSI норм, но видимо есть какие-то подводные камни, раз эта идея не стала популярной.
Возможно виной тому отсутствие эскейпа html и уязвимость к XSS. Может быть, просто не хватало возможностей (не увидел поддержки циклов).
Еще так и не нашел единого описания стандарта. Сложилось впечатление, что каждый веб-сервер (Apache, Jigsaw и т.п.)
поддерживает свой несовместимый набор команд
DexterHD
15.03.2018 20:00-1Купите лучше какую-нибудь книгу, лучше фундаментальную, касающуюся веб разработки в целом, истории вэба, истории развития браузеров и HTML.
Harrix Автор
15.03.2018 20:10Зачем?
DexterHD
15.03.2018 21:06Потому что изучение фундаментальных трудов это отличная инвестиция в будущее, если конечно вы хотите стать профессионалом в области разработки ПО. Конечно можно изучать все исключительно по статьям и Ютубам, но вряд ли это поможет сделать карьеру или найти работу на которой можно будет решать сложные и интересные задачи.
Zenitchik
15.03.2018 21:15Литература, представляющая сугубо исторический интерес, поможет сделать карьеру с ещё меньшей вероятностью.
Хотя, конечно, чтиво занимательное.DexterHD
15.03.2018 21:30Труды Танненбаума, «Архитектура компьютеров», «Операционные Системы», «Компьютерные Сети», это сугубо исторический интерес? Или может быть «Код» Петцольда представляет сугубо исторический интерес? А может быть Деннис Ритчи «Язык Си» ни кому не нужная историческая книжка? «Чистый код», «Программист прагматик», «Совершенный код», «Архитектура корпоративных приложений», или вот… Кнут «Искусство программирования», которая была написана пол века назад. Это все сугубо исторические книги? Я на 100% уверен что люди которые не читали хотя бы половину из перечисленного, понятия не имеют как писать программы, более того, в голове у них как правило каша и я регулярно с этим сталкиваюсь когда приходится нанимать людей на работу.
Любая фундаментальная литература не имеет срока давности и дает глубокие знания и понимание всего того что программист использует.
А читать книги по языкам программирования или не дай бог по Библиотекам, типа «Изучаем jQuery» или программируем на «React» — пустая трата времени.Harrix Автор
15.03.2018 22:27+1Какое отношение, например, «Совершенный код» относится к «книге, лучше фундаментальной, касающуюся веб разработки в целом, истории вэба, истории развития браузеров и HTML». Или тот же Кнут? А вам сказали именно насчет книг истории развития IT, про которые вы упомянули. А вы в ответ привели список отличных книг, но они про другое.
А историю веба и так далее, как считаю, знаю достаточно. И читать еще какие-то дополнительные книги не хочется.DexterHD
15.03.2018 22:56-2Это какие-то старые основы. Пока я нахожу статьи 2011 или 2012 года, где рассказывается как SSI использовать на Apache. И статей как-то маловато. Тогда подскажите, пожалуйста, мне недалекому, который основ не знает, как с помощью SSI сгенерировать статические html файлы.
Достаточно хорошо чтобы писать такое? Ну ок. У вас кстати в постановке задачи первым стоит слово «Сайт», изучите чем «сайт» отличается от набора html страниц.Harrix Автор
16.03.2018 00:42Достаточно хорошо чтобы писать такое?
Да, я так считаю. Вы считаете, что каждый человек должен знать никем не используемую технологию? Таких технологий вагон и маленькая тележка.
У вас кстати в постановке задачи первым стоит слово «Сайт», изучите чем «сайт» отличается от набора html страниц.
Из-за того, что в статье опущено описания заливки файлов на хостинг никак не меняет сути.
А про свои косяки с книгами вы решили умолчать… Ладно.DexterHD
16.03.2018 01:12Да, я так считаю. Вы считаете, что каждый человек должен знать никем не используемую технологию? Таких технологий вагон и маленькая тележка.
Я считаю что web-разработчик должен хорошо знать фундамент на котором стоит Web. А web стоит на целой пачке технологий некоторый из которых наложены одна на другую или являются развитием более старых вещей. И чтобы оптимально и правильно решать задачи нужно хотя бы иметь общее представление о всех них. Книги отсылающие к истории веба как нельзя лучше подходят для того чтобы вообще понять почему современный вэб такой какой он есть и где какие технологии стоит использовать, а где они избыточны или не нужны.
DexterHD
15.03.2018 23:04Ну или можно сменить постановку задачи и статью на: «Генерируем набор HTML страниц с помощью WebPack 4», тогда все вопросы и споры отпадут сами собой.
Вот кстати неплохая цитатка про SSI, источник указывать не буду, вы и сами знаете:
Static websites may still use server side includes (SSI) as an editing convenience, such as sharing a common menu bar across many pages. As the site's behaviour to the reader is still static, this is not considered a dynamic site.
Harrix Автор
16.03.2018 00:49Хм… Тут не смогу не согласиться и наоборот согласится. Например, в том же источнике ниже написано «Server-side dynamic pages are generated „on the fly“ by computer code that produces the HTML (CSS are responsible for appearance and thus, are static files).» Что как бы входит в противоречие с цитатой, которую вы привели. Но это уже чисто терминалогический спор: статический сайт определяется со стороны клиента или сервера.
DexterHD
16.03.2018 01:05Там 2 раздела. Первый называется Static website, второй Dynamic website. Я привел текст из первого раздела, вы приводите со второго. Нет ни каких противоречий. Просто прочитайте эти разделы и все станет на свои места.
Вы утверждали что SSI сделает сайт динамическим, хотя это не так. И именно для этого я посоветовал ознакомится с фундаментальной литературой.
Вы путаетесь в терминологии в данном конкретном случае, а терминология крайне важная вещь в нашей отрасли.
К слову я тоже не семи пядей во лбу, поэтому частенько поднимаю теорию и вам того же советую.
redfs
16.03.2018 07:58Но это уже чисто терминалогический спор: статический сайт определяется со стороны клиента или сервера
Коллега, поясните, пожалуйста, вашу мысль — «статический сайт со стороны клиента»?
Вам действительно надо привести в порядок терминологию, хотя бы для того, чтобы ваши читатели вас правильно понимали.
beduin01
13.03.2018 16:40Боже, в какое дно превратили Интернет любители NodeJS. Это не сайты, а уродцы какие-то. Тоже самое можно сделать в десять раз проще если выкинуть весь этот ужас.
Harrix Автор
13.03.2018 17:48Это не сайты, а уродцы какие-то.
Уродство с точки зрения сборки или с точки зрения получившегося результата? Если второе, то что там уродского? Обычныt Bootstrap страницы.
Тоже самое можно сделать в десять раз проще если выкинуть весь этот ужас.
Специально в статье приведена постановка задачи. Скажите как её можно решить в десять раз проще. Честно, буду очень признателен.beduin01
13.03.2018 18:00С точки зрения процесса. Нафиг NodeJS нужен для сайтов я так и не понял.
Типичный мой проект:
1. Сгенерированные статические роутеры через vibed c шаблонизатором pug/diet
2. Динамические части на vuejs подгружаемые через http-vue
3. css по вкусу, которую можно прям в компонентах vue разместить.
В итоге проект весит сотни килобайт (исходники). Переносится с компа на комп копи-пастом. Никаких мучительных конфигураций веб-пака и развертывания NodeJS.Harrix Автор
13.03.2018 18:11Смутно представляю эти технологии, так что задам несколько вопросов.
Правильно ли я понимаю, что это получается скорее web приложение, чем обычные web страницы, где html код можно посмотреть просто в html файлах?
Как я понимаю, вначале были прописаны эти исходники, настроены и всё такое. А чем тогда от предложенного способа отличается? Мне нужно будет в другом проекте написать толькоnpm i
и вся настроенная система появится опять.
Где-нибудь можно посмотреть на пример такого проекта? Возможно от webpack перейду к vue.js.beduin01
13.03.2018 19:01Нет получаются очень удобные html-страницы. Которые генерятся на сервере т.е. их видит поисковик. Всякие модные интерактивные компоненты можно оформлять именно как веб-компоненты и подгружать в нужные места.
Тоесть проблем с индексацией не будет. Страницы все открываются пулей.
pug шаблон позволяет описать каркас сайта один раз и потом просто цеплять к нему нужные блоки.
Пример кину в личку.
justboris
14.03.2018 02:14vibed — это вы имеете в виду vibe-d, веб-сервер на D?
beduin01
14.03.2018 10:48Да, именно
justboris
14.03.2018 11:21+1Так это же веб-сервер, его запускать где-то надо.
Статья про принципиально другой подход. Статический сайт собирается из исходников скриптом и получается несколько html-файлов. Эти файлы загружаются на любое файлохранилище (surge, netlify или Github pages). Затем прикручиваете кастомный домен, и сайт готов. Поддерживать запущенный сервер не надо вообще.
DexterHD
13.03.2018 19:57Открыть любой текстовый редактор и решить. В 10 раз проще и главное быстрее. Постановка задачи на самом деле, это первое предложение, а второе предложение:
Необходимо написать проект, который бы собирал наш сайт из исходников:
Это создание надуманной проблемы которую потом всю остальную часть статьи приходится решать.Harrix Автор
13.03.2018 20:11+1Открыть любой текстовый редактор и решить.
Ввиду того, что раньше так и делал, то могу оценить насколько эти два варианта. Во-первых, без SCSS работу с CSS я сейчас вообще не представляю. Повышает удобство работы во много раз. Можно найти программы, которые позволяют работать с SASS без node.js (например, Koala), но внутри них также стоят настроенные бандлеры. Во-вторых, работа с js с модулями и компоновкой в один файл также сильно повышает удобство работы (но не так сильно). В-третьих, шаблонизаторы с возможностью написания условий, циклов — так это вообще красота. А вручную прописывать один и тот же код шапки, например, в сотнях html файлах — это ад.
vvadzim
13.03.2018 16:58А такой инструмент parceljs.org рассматривали?
Для подобных задач вроде как подходит.Harrix Автор
13.03.2018 17:50Опа… Надо будет на него глянуть. В декабре было 8725 звезд на гихабе, а сейчас 20338! Правда число установок в node.js в месяц у webpack пока еще сильно больше: 13 188 708 против 35 097. Но обязательно посмотрю на этого зверя.
vvadzim
13.03.2018 19:27+1Webpack сильно врос в экосистему — те же create-react-app/create-react-native-app.
Webpack появился и обошел browserify как ответ на необходимость экспериментировать и настраивать.
А parceljs появился когда стэк устаканился и с конфигами наигрались.
Кстати, у того же browserify все ещё 3,5 млн загрузок. Раз вас это радует)
Odrin
14.03.2018 12:13И если добавить стили библиотеки в наш style.scss, то file-loader будет искать картинки библиотеки lightgallery в моей папке src/img, а не там, где они находятся. И побороть я это не смог.
Если я правильно понял суть проблемы, то она решается с помощью resolve-url-loader
maolo
14.03.2018 22:10Как раз в процессе переноса сборки с gulp'а на webppack — так что Ваша статья в руку, есть то, с чем я еще не разобрался.
И если добавить стили библиотеки в наш style.scss, то file-loader будет искать картинки библиотеки lightgallery в моей папке src/img, а не там, где они находятся. И побороть я это не смог.
Опция exclude не поможет, примерно как здесь указано — https://stackoverflow.com/questions/44211666/how-to-exclude-bootstrap-files-when-css-modules-is-enabled ?
Обратите внимание на то, что в точках входа entryмы добавили новый входной файл style.scss
Кстати, если в output указать не конкретное имя, а чанки, напр.,
filename: "js/[name].js",
то в папке dist/js появится style.js… пустой) (ну, не совсем пустой — там будет вебпаковаская обертка, но по сути, ничего не делающая, поскольку стили извлечены extract плагином)
Поэтому для итоговой сборки рекомендую использовать не команду *npm run build, а команду npm run build-and-beautify.
В npm можно указывать команды с префиксами "pre" и "post", которые запустяться, соотвественно, до и после основной команды, т.е. вот это:
"scripts": { "build-and-beautify": "webpack --mode production && html dist/*.html --indent-size 2", "beautify": "html dist/*.html --indent-size 2" },
можно записать так:
"scripts": { "build": "webpack --mode production && html dist/*.html --indent-size 2", "postbuild": "html dist/*.html --indent-size 2" },
команда postbuild запуститься автоматически после выполнения build
maolo
14.03.2018 22:18Еще очень рекомендую эту книгу о вебпак — SurviveJS — Webpack
И курс Ильи Кантора (хоть и 2015 г., но все равно полезный в плане понимация настройки Webpack) — Скринкаст по Webpack
maolo
15.03.2018 00:37поправка к "build-and-beautify":
"scripts": { "beautify": "html dist/*.html --indent-size 2", "build": "webpack --mode production", "postbuild": "npm run beautify" },
Alter2
15.03.2018 01:17-1Мда, простые статичные сайты уже не те.
В чем преимущества такого подхода вместо того чтобы просто выложить файлы на сервер?Harrix Автор
15.03.2018 08:50Прежде чем выложить файлы, их нужно как-то подготовить. Например, формируется документация в виде HTML страниц. Страниц таких больше сотни. И допустим, я писал их вручную. И потом мне в шапке каждой страницы нужно что-то поменять. Как?
koutsenko
15.03.2018 23:17Интересно, можно ли использовать JSX в отрыве от реакта. Как шаблонизатор. В итоге, сочетая с описанной в статье конфигурацией, в итоге можно посадить дизайнера-верстальщика делать макет, а потом скопировать верстку в реальный проект (естесственно с некоторыми правками — другим разбиением на компоненты, с заточками под условное отображение и т.п.).
DexterHD
15.03.2018 23:30JSX is an XML-like syntax extension to ECMAScript without any defined semantics.
This specification does not attempt to comply with any XML or HTML specification. JSX is designed as an ECMAScript feature and the similarity to XML is only for familiarity.
anttoshka
Спасибо, как раз на днях занимался подобным вопросом. Ранее читал, что сборка webpack-ом стилей, html и т.п. медленнее чем галпом. Вы не пробовали сравнить быстродействие? У меня есть отдельно настроенная сборка галп+вебпак с шаблонизатором jade. Так там при большом количестве jade миксинов пересборка длится ощутимое время. Если же webpack 4 покажет лучшее быстродействие — стоит на него в таком случае переезжать.
PaulZi
gulp быстрее, однако webpack это несколько иной инструмент. Webpack собирает бандлы с учётом зависимостей и умеет tree-snaking. То есть если типичный сценарий с gulp собираем все стили в одном файлы, скрипты в другом. С вебпаком, если у вас есть некий компонент, которому требуют скрипты и стили, а также имеет зависимости, то вы все стили и зависимости подключаете непосредственно в скрипте этого компонента. Поэтому если вдруг вам компонент больше не нужен будет, и вы перестанете его использовать, он у вас перестанет попадать в бандл.