Настраиваем полноценную сборку

Перед тем как начать

В предыдущем уроке мы создали нашу первую сцену при помощи самого простого подключения three.js, если вы это пропустили, то советую вернуться!

То, как мы с вами в первом уроке подключили three.js - самый простой вариант. К сожалению, у него есть свои недостатки, а именно при том методе подключения у нас нет доступа к некоторым классам three.js, поскольку иначе файл будет слишком тяжелый.

Настраиваем полноценную сборку

Поэтому нам нужен другой способ подключения, который бы позволил нам использовать эти спрятанные классы.

Существуем много способов как это можно сделать, но мы воспользуемся одним из самых популярных - соберем свой бандлер.

Что такое бандлер (сборщик)?

Бандлер - это утилита, в которую можно отправлять различные файлы, например, JavaScript, TypeScript, CSS, HTML, медиа и т.д. Бандлер соберет переданную ему статику, применит некоторые модификации к ней и на выходе вернет бандл, который можно напрямую запустить в вебе.

Если копнуть поглубже, то бандлер может делать намного больше. Например, при помощи бандлера можно развернуть локальный сервер, настраивать зависимости, оптимизировать статику, минимизировать код, заливать на сервер и т.д.

Webpack

Webpack - один из популярных самых бандлеров. С его помощью можно сделать практически все, что необходимо для сборки проекта, а так же крайне радует очень хорошо написанная документация и огромное комьюнити разработчиков.

Приступаем к настройке

Для начала давайте загрузим NodeJS.

После загрузки приступим к созданию нужной нам архитиктуре папок.

Откроем терминал, создадим папку проекта и перейдем в нее:

mkdir threejs-cookbook &&cd threejs-cookbook

Проинициализируем npm проект:

npm init -y

Далее нам нужно установить необходимые нам пакеты для webpack (их много, но они нужны для нормальной настройки сборки и минификации, сама по себе настройка webpack - та еще магия, если будет много голосов, то могу в дальнейшем записать курс по webpack):

npm install webpack webpack-cli webpack-dev-server webpack-merge clean-webpack-plugin copy-webpack-plugin @babel/core @babel/preset-env babel-loader css-loader file-loader html-loader html-webpack-plugin mini-css-extract-plugin portfinder-sync raw-loader style-loader ip --save-dev

Следующим шагом создадим в папке проекта нужные нам директории:

mkdir bundler src static
  • В директории bundler - будем хранить все файлы, которые связаны с настройкой бандлера
  • В директории src - будут хранится все файлы исходного кода
  • В директории static - будет вся статика, которая нужна нам для проекта

Создадим основные файлы настройки webpack:

touch bundler/webpack.common.js bundler/webpack.dev.js bundler/webpack.prod.js

В файле bundler/webpack.common.js будет храниться общая настройка webpack для сборки для разработки и для итогового прода:

const CopyWebpackPlugin = require('copy-webpack-plugin'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const MiniCSSExtractPlugin = require('mini-css-extract-plugin'); const path = require('path'); module.exports = { entry: path.resolve(__dirname, '../src/script.js'), output: { hashFunction: 'xxhash64', filename: 'bundle.[contenthash].js', path: path.resolve(__dirname, '../dist') }, devtool: 'source-map', plugins: [ new CopyWebpackPlugin({ patterns: [ { from: path.resolve(__dirname, '../static'), noErrorOnMissing: true } ] }), new HtmlWebpackPlugin({ template: path.resolve(__dirname, '../src/index.html'), minify: true }), new MiniCSSExtractPlugin() ], module: { rules: [ { test: /\.(html)$/, use: [ 'html-loader' ] }, { test: /\.js$/, exclude: /node_modules/, use: [ 'babel-loader' ] }, { test: /\.css$/, use: [ MiniCSSExtractPlugin.loader, 'css-loader' ] }, { test: /\.(jpg|png|gif|svg)$/, type: 'asset/resource', generator: { filename: 'assets/images/[hash][ext]' } }, { test: /\.(ttf|eot|woff|woff2)$/, type: 'asset/resource', generator: { filename: 'assets/fonts/[hash][ext]' } } ] } };

В файле bundler/webpack.dev.js будет храниться настройка webpack для сборки для разработки:

const path = require('path'); const { merge } = require('webpack-merge'); const commonConfiguration = require('./webpack.common.js'); const ip = require('ip'); const infoColor = (message) => `\u001b[1m\u001b[34m${message}\u001b[39m\u001b[22m`; module.exports = merge( commonConfiguration, { stats: 'errors-warnings', mode: 'development', infrastructureLogging: { level: 'warn', }, devServer: { host: 'localhost', port: 3000, open: true, https: false, allowedHosts: 'all', hot: true, watchFiles: ['src/**', 'static/**'], static: { watch: true, directory: path.join(__dirname, '../static') }, client: { logging: 'none', overlay: true, progress: false }, onAfterSetupMiddleware: function(devServer) { const port = devServer.options.port const https = devServer.options.https ? 's' : '' const localIp = ip.address() const domain1 = `http${https}://${localIp}:${port}` const domain2 = `http${https}://localhost:${port}` console.log(`Проект запущен на:\n - ${infoColor(domain1)}\n - ${infoColor(domain2)}`) } } } );

В файле bundler/webpack.prod.js будет храниться настройка webpack для сборки для прода:

const { merge } = require('webpack-merge'); const commonConfiguration = require('./webpack.common.js'); const { CleanWebpackPlugin } = require('clean-webpack-plugin'); module.exports = merge( commonConfiguration, { mode: 'production', plugins: [ new CleanWebpackPlugin() ] } );

Установим three.js:

npm install three --save-dev

И изменим скрипты в package.json на:

"build": "webpack --config ./bundler/webpack.prod.js", "dev": "webpack serve --config ./bundler/webpack.dev.js"

Давайте переместим базовые файлы, которые мы создали в прошлых уроках и немного их изменим:

Файл src/index.html должен выглядеть примерно вот так (тут мы убрали подключение скриптов, за нас это сделает бандлер):

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>ThreeJS-Cookbook</title> </head> <body> <canvas class="canvas-js"></canvas> </body> </html>

Файл src/script.js выглядит примерно вот так:

import * as THREE from 'three'; // Подключим файл со стилями import './style.css'; // Сцена const scene = new THREE.Scene(); // Объект const geometry = new THREE.BoxGeometry(1, 1, 1); const material = new THREE.MeshBasicMaterial({ color: 'purple', wireframe: true }); const mesh = new THREE.Mesh(geometry, material); scene.add(mesh); // Объект с размерами const sizes = { width: 600, height: 600 }; // Камера const camera = new THREE.PerspectiveCamera(75, sizes.width / sizes.height); camera.position.z = 3; scene.add(camera); // Отрисовщик const renderer = new THREE.WebGLRenderer({ canvas: document.querySelector('canvas.canvas-js'), alpha: true, }); renderer.setSize(sizes.width, sizes.height); renderer.render(scene, camera);

Так же давайте создадим пустой файл со стилями:

touch src/style.css

И сейчас, запустив в консоли скрипт npm run dev у вас откроется браузер с нашим кубиком, поздравляю!

Я стараюсь создать комьюнити людей, которым интересна веб-разработка, 3d и путешествия, поэтому зову вас присоединиться к моему блогу в telegram!

Следующий урок

Начать дискуссию