В ближайшие недели мы будем изучать различные паттерны, техники и стратегии при работе с LitElement. Это мини-серия из двух частей о создании базового шаблона для SPA (одностраничных приложений) с использованием LitElement, Webpack и Boostrap. В итоге мы получим очень полезный стартовый шаблон, который можно использовать со всеми вашими проектами LitElement.
Примечание: поскольку LitElement очень «легкий» и ненавязчивый по своей природе, все в этой статье можно легко изменить, чтобы исключить LitElement с помощью стандартных веб-компонентов ES6.
Почему LitElement + Bootstrap + Webpack? Если вам интересно, почему LitElement, я бы посоветовал вам прочитать мои десять главных причин использовать Polymer LitElement. Bootstrap вряд ли нуждается в качестве причины. А вебпак? Нам нужно что-то, чтобы помочь нам в процессе разработки и сборки. Честно говоря, мой файл gulp становился все сложнее и сложнее. И мои приложения, созданные с помощью веб-пакета, занимали меньше места и работали быстрее.
Есть много статей о webpack. Вместо того, чтобы углубляться в преимущества webpack по сравнению с gulp, в этой статье мы сосредоточимся на том, чтобы заставить webpack работать в шаблоне запуска, который можно применять в самых разных ситуациях — чтобы мы могли сосредоточиться на том, чтобы «сделай это»!
Давайте начнем. Создайте новый каталог для работы и инициализируйте npm.
$ npm init
Установите Webpack, LitElement и Bootstrap Native.
$
npm install --save-dev webpack webpack-dev-server \
webpack-cli webpack-merge copy-webpack-plugin \
html-webpack-plugin clean-webpack-plugin \
$ npm install --save-dev style-loader css-loader \
babel-loader @babel/core @babel/preset-env
$ npm install --save @webcomponents/webcomponentsjs
$ npm install --save lit-element
$ npm install --save bootstrap.native
$ npm install --save properties-reader
$ npm install --save @bundled-es-modules/axios
Загрузите загрузочный шаблон Material Kit от Creative Tim, разархивируйте файл в свою рабочую папку и переименуйте корневую папку архива в src следующим образом:
$ unzip ~/Downloads/material-kit-master.zip $ mv material-kit-master src
Давайте начнем настраивать наш конвейер разработки с помощью webpack. Теперь мы создадим подкаталог Create a tools в нашей рабочей папке и создадим новый файл: webpack.development.js.
$ mkdir tools $ nano webpack.development.js
Вставьте следующий код JavaScript в webpack.development.js:
const CopyWebpackPlugin = require('copy-webpack-plugin'); module.exports = () => ({ module: { rules: [ { test: /\.css$/, use: ['style-loader', 'css-loader'] } ] }, devtool: 'source-map' });
Это настраивает веб-пакет для обработки файлов CSS без полного обновления (перевод: изменения CSS будут обновляться быстрее для нас).
Теперь создадим аналогичный файл: webpack.production.js:
const MiniCssExtractPlugin = require('mini-css-extract-plugin'); module.exports = () => ({ module: { rules: [ { test: /\.css$/, use: [MiniCssExtractPlugin.loader, 'css-loader'] } ] }, plugins: [new MiniCssExtractPlugin()] });
Это позволит webpack минимизировать CSS для производственного использования.
Теперь создайте в рабочей папке файл webpack.config.js:
const webpack = require('webpack'); const { resolve } = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const webpackMerge = require('webpack-merge'); const CopyWebpackPlugin = require('copy-webpack-plugin'); const {CleanWebpackPlugin} = require('clean-webpack-plugin'); const webcomponentsjs = './node_modules/@webcomponents/webcomponentsjs'; const PropertiesReader = require('properties-reader'); const appProperties = PropertiesReader('./src/assets/app.properties')._properties; const polyfills = [ { from: resolve(`${webcomponentsjs}/webcomponents-*.{js,map}`), to: 'vendor', flatten: true }, { from: resolve(`${webcomponentsjs}/bundles/*.{js,map}`), to: 'vendor/bundles', flatten: true }, { from: resolve(`${webcomponentsjs}/custom-elements-es5-adapter.js`), to: 'vendor', flatten: true } ]; const assets = [ { from: 'src/assets', to: 'assets/' }, { from: 'src/*.html', to: '/' } ]; const plugins = [ new CleanWebpackPlugin(), new webpack.ProgressPlugin(), new HtmlWebpackPlugin({ chunks: ['app'], filename: 'index.html', template: './src/index.html', minify: { collapseWhitespace: true, minifyCSS: true, minifyJS: true } }), new CopyWebpackPlugin([...polyfills, ...assets], { ignore: ['.DS_Store'] }) ]; module.exports = ({ mode, presets }) => { return webpackMerge({ entry: { app: './src/index.js' }, externals: { 'appProperties': JSON.stringify(appProperties) }, mode, output: { filename: '[name].[chunkhash:8].js', publicPath: '/', }, module: { rules: [{ test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader', options: { plugins: ['@babel/plugin-syntax-dynamic-import'], presets: [[ '@babel/preset-env', { useBuiltIns: 'usage', targets: '>1%, not dead, not ie 11' } ]] } }] }, plugins } ); //webpackMerge };
Массив полифиллов — это просто список местоположений библиотеки веб-компонентов, которые мы хотим, чтобы веб-пакет добавил в наше приложение. Массив активов перечисляет местоположение статических ресурсов, таких как файлы html, изображения, файлы css и т. д.
Массив плагинов будет запускать различные плагины, которые мы хотим, чтобы вызывал веб-пакет, в том числе: CleanWebpackPlugin, webpack.ProgressPlugin, HtmlWebpackPlugin и CopyWebpackPlugin.
CleanWebpackPlugin очистит папку «./dist». Это расположение по умолчанию для файлов вашей производственной сборки.
Webpack.ProgressPlugin просто распечатывает индикатор прогресса, когда выполняет свою работу.
Плагин CopyWebpackPlugin просто копирует статические ресурсы, перечисленные в массиве assets.
Наконец, HtmlWebpackPlugin создает для вас файл HTML5, который включает в себя все ваши пакеты веб-пакетов в теле. В нашем примере здесь он генерирует наш основной index.html.
Теперь перейдем к нашему объекту webpackMerge. Ключ входа указывает файл JavaScript, который будет служить единственной точкой входа в наш SPA: index.js.
Запись externals позволяет нам настроить файл свойств, к которому мы можем получить доступ в нашем приложении. Имея опыт работы с Java/JEE, я долго искал хорошие решения. Я с гордостью покажу вам, как это работает в part deux.
Выходные ключи позволяют нам указать соглашение об именах выходных файлов .js, а также общедоступный путь, который будет иметь приложение.
Загрузчик babel будет использовать Babel для переноса нашего кода ES6 для совместимости с браузером.
Чтобы свернуть все это в удобной для использования среде, мы откроем наш файл package.json и вставим следующее в свойство scripts:
"scripts": { "webpack": "webpack", "webpack-dev-server": "webpack-dev-server --history-api-fallback --disable-host-check", "prod": "npm run webpack -- --env.mode production --env.presets serviceworker", "dev": "npm run webpack-dev-server -- --env.mode development --port 8086" },
Это определяет некоторые пакетные сценарии, чтобы мы могли легко запускать процессы разработки и сборки. Чтобы запустить автоматически обновляемый сервер разработки веб-пакетов, работающий на порту 8086, мы вводим:
$ npm run dev
и собрать производственный дистрибутив нашего приложения в папке «./dist»:
$ npm run prod
Теперь выполните «npm run dev» и укажите в браузере
Фух — и все это только для того, чтобы запустить index.html! А если серьезно, теперь у нас есть процесс сборки, который будет поддерживать наш код LitElement, работающий с загрузочным шаблоном.
Обратите внимание, что большая часть конфигурации веб-пакета, представленная в этой статье, не относится к LitElement и будет работать для любого другого проекта JavaScript. Я настоятельно рекомендую познакомиться с webpack поближе всем, кто заинтересован.
На данный момент я собрал быструю и грязную конфигурацию веб-пакета для всех наших руководств по LitElement. Эта установка получит «Mr. Нетерпение без предварительных знаний о веб-пакете», готовое копаться для кодирования некоторых веб-компонентов LitElement ES6.
Следующая часть этой серии из двух частей будет посвящена встраиванию веб-компонентов LitElement в этот загрузочный шаблон. Быть в курсе!