В ближайшие недели мы будем изучать различные паттерны, техники и стратегии при работе с 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» и укажите в браузере

http://локальный:8086

Фух — и все это только для того, чтобы запустить index.html! А если серьезно, теперь у нас есть процесс сборки, который будет поддерживать наш код LitElement, работающий с загрузочным шаблоном.

Обратите внимание, что большая часть конфигурации веб-пакета, представленная в этой статье, не относится к LitElement и будет работать для любого другого проекта JavaScript. Я настоятельно рекомендую познакомиться с webpack поближе всем, кто заинтересован.

На данный момент я собрал быструю и грязную конфигурацию веб-пакета для всех наших руководств по LitElement. Эта установка получит «Mr. Нетерпение без предварительных знаний о веб-пакете», готовое копаться для кодирования некоторых веб-компонентов LitElement ES6.

Следующая часть этой серии из двух частей будет посвящена встраиванию веб-компонентов LitElement в этот загрузочный шаблон. Быть в курсе!