Updating webpack

This commit is contained in:
László Károlyi 2019-11-26 21:07:47 +01:00
parent d5fc93419f
commit 5a1a0f1d1d
Signed by: karolyi
GPG key ID: 2DCAF25E55735BFE
15 changed files with 369 additions and 199 deletions

View file

@ -1,4 +1,37 @@
{
"presets": ["stage-0", "stage-2", "es2015", "es2017"],
"plugins": ["transform-runtime"],
"presets": [
"@babel/preset-env"
],
"plugins": [
[
"@babel/plugin-transform-runtime",
{}
],
"@babel/plugin-syntax-dynamic-import",
"@babel/plugin-syntax-import-meta",
"@babel/plugin-proposal-class-properties",
"@babel/plugin-proposal-json-strings",
[
"@babel/plugin-proposal-decorators",
{
"legacy": true
}
],
"@babel/plugin-proposal-function-sent",
"@babel/plugin-proposal-export-namespace-from",
"@babel/plugin-proposal-numeric-separator",
"@babel/plugin-proposal-throw-expressions",
"@babel/plugin-proposal-export-default-from",
"@babel/plugin-proposal-logical-assignment-operators",
"@babel/plugin-proposal-optional-chaining",
[
"@babel/plugin-proposal-pipeline-operator",
{
"proposal": "minimal"
}
],
"@babel/plugin-proposal-nullish-coalescing-operator",
"@babel/plugin-proposal-do-expressions",
"@babel/plugin-proposal-function-bind"
]
}

3
.browserslistrc Normal file
View file

@ -0,0 +1,3 @@
last 2 versions
> 5%
not dead

View file

@ -8,5 +8,5 @@ charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.{js,scss}]
[*.{js,scss,yaml}]
indent_size = 2

View file

@ -1,12 +1,10 @@
{
"ecmaFeatures": {
"modules": true
},
"env": {
"browser": true,
"node": true
},
"parser": "babel-eslint",
"extends": ["eslint:recommended", "airbnb-base"],
"rules": {
"no-continue": [0],
"no-console": [1],
@ -15,17 +13,18 @@
"strict": [2, "never"],
"max-len": [2, {"code": 80, "tabWidth": 4, "ignoreUrls": true}],
"no-restricted-syntax": "off",
"max-classes-per-file": "off",
"import/no-extraneous-dependencies": [
"error",
{
"devDependencies": true
}
],
"import/prefer-default-export": ["off"]
"import/prefer-default-export": ["off"],
"operator-linebreak": "off"
},
"globals": {
},
"plugins": [
],
"extends": ["eslint:recommended", "airbnb-base"]
]
}

View file

@ -1,4 +1,5 @@
[settings]
multi_line_output=4
skip=backend/forum/wsgi.py
skip-glob=*node_modules/*
; skip=backend/ticketshop/wsgi.py
; skip-glob=*node_modules/*
not_skip=__init__.py

View file

@ -3,8 +3,8 @@ from django.conf.urls import include, url
from .views import LoginView, SettingsView, logout
urlpatterns = [
url(r'^login/$', view=LoginView.as_view(), name='login'),
url(r'^logout/$', view=logout, name='logout'),
url(r'^settings/$', view=SettingsView.as_view(), name='settings'),
url('^', include('django.contrib.auth.urls')),
url(regex=r'^login/$', view=LoginView.as_view(), name='login'),
url(regex=r'^logout/$', view=logout, name='logout'),
url(regex=r'^settings/$', view=SettingsView.as_view(), name='settings'),
url(regex='^', view=include('django.contrib.auth.urls')),
]

View file

@ -1,17 +1,19 @@
from django.conf.urls import url
from forum.base.views.api import (
v1_archived_topics_start, v1_find_users_by_name, v1_topic_list_page,
v1_user_short)
from .views.md_helper import md_parser
urlpatterns = [
url(r'^v1/user-short/(?P<slug_list>[a-z0-9-,]+)/$',
v1_user_short, name='v1-user-short'),
url(r'^v1/topic-list-page/',
v1_topic_list_page, name='v1-topic-list-page'),
url(r'^v1/archived-topics-start/',
v1_archived_topics_start, name='v1-archived-topics-start'),
url(r'^v1/find-users-by-name/', v1_find_users_by_name,
url(regex=r'^v1/user-short/(?P<slug_list>[a-z0-9-,]+)/$',
view=v1_user_short, name='v1-user-short'),
url(regex=r'^v1/topic-list-page/',
view=v1_topic_list_page, name='v1-topic-list-page'),
url(regex=r'^v1/archived-topics-start/',
view=v1_archived_topics_start, name='v1-archived-topics-start'),
url(regex=r'^v1/find-users-by-name/', view=v1_find_users_by_name,
name='v1-find-users-by-name'),
url(r'^v1/md-parser/', md_parser, name='md-parser'),
url(regex=r'^v1/md-parser/', view=md_parser, name='md-parser'),
]

View file

@ -31,5 +31,5 @@ urlpatterns = [
if settings.DEBUG:
# Add debug toolbar
import debug_toolbar
urlpatterns += [url(regex=r'^__debug__/',
view=include(debug_toolbar.urls))]
urlpatterns += [
url(regex=r'^__debug__/', view=include(arg=debug_toolbar.urls))]

View file

@ -1,4 +1,6 @@
const path = require('path')
const postCssConfigPath = path
.resolve(path.join(__dirname, '..', '..', 'postcss.config.js'))
module.exports = {
context: __dirname,
@ -68,38 +70,8 @@ module.exports = {
}],
},
{
// Transpile ES6 to ES5 in Bootstrap V4
test: /bootstrap\/js\/src\/tooltip.js$/,
use: [{
loader: 'imports-loader',
options: {
jQuery: 'jquery',
Tether: 'tether',
},
}, {
loader: 'babel-loader',
options: {
babelrc: true,
},
}],
},
{
// Transpile ES6 to ES5 in Bootstrap V4
test: /bootstrap\/js\/src\/.*\.js$/,
use: [{
loader: 'imports-loader',
options: {
jQuery: 'jquery',
},
}, {
loader: 'babel-loader',
options: {
babelrc: true,
},
}],
},
{
// Transpile ES6 to ES5
// https://stackoverflow.com/a/54520451/1067833 ?
// Use Babel everywhere except node_modules
test: /\.js$/,
// exclude: /node_modules/,
use: [{
@ -109,7 +81,8 @@ module.exports = {
},
}],
},
{ test: /\.json$/,
{
test: /\.json$/,
use: [{
loader: 'json-loader',
}],
@ -126,6 +99,10 @@ module.exports = {
loader: 'css-loader',
}],
},
{
loader: 'postcss-loader',
options: { config: { path: postCssConfigPath }, sourceMap: true },
},
{
test: /.*\.html(\?.*)?$/,
use: [{
@ -135,10 +112,18 @@ module.exports = {
],
},
// This will be extended later on from configs that inherit this
// module
plugins: [
],
resolve: {
modules: [
'node_modules',
path.resolve(__dirname, '../..'),
path.resolve(__dirname, '../../node_modules'),
],
extensions: ['.js'],
},
optimization: {
},
}

View file

@ -4,10 +4,20 @@
'use strict'
const path = require('path')
const configBase = require('./config.base')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const webpack = require('webpack')
const BundleTracker = require('webpack-bundle-tracker')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const configBase = require('./config.base')
const postCssConfigPath = path
.resolve(path.join(__dirname, '..', '..', 'postcss.config.js'))
const extractCSS = new MiniCssExtractPlugin({
// Options similar to the same options in webpackOptions.output
// both options are optional
filename: 'stylesheets/[name].css',
chunkFilename: 'stylesheets/[id].css',
})
let key
const tempEntry = {}
@ -15,11 +25,12 @@ const tempEntry = {}
for (key of Object.keys(configBase.entry)) {
const item = configBase.entry[key].slice()
// Copy the original list
// item.unshift('webpack/hot/only-dev-server')
item.unshift('webpack/hot/dev-server')
if (key !== 'loader') {
// The loader doesn't get a HMR connection (everything else does)
item.unshift('webpack-dev-server/client?http://localhost:3000/')
// item.unshift('webpack-dev-server/client?http://192.168.1.130:3000/')
// item.unshift(`webpack-dev-server/client?http://${devHostname}:3000/`)
}
tempEntry[key] = item
}
@ -36,42 +47,50 @@ configBase.devtool = 'source-map'
configBase.module.rules.push({
test: /\.scss$/,
use: [{
loader: 'style-loader',
options: {
useable: true,
use: [
{ loader: 'style-loader' },
{ loader: 'css-loader', options: { sourceMap: true } },
{
loader: 'postcss-loader',
options: { config: { path: postCssConfigPath }, sourceMap: true },
},
}, {
loader: 'css-loader',
options: {
sourceMap: true,
{
loader: 'sass-loader',
options: {
sourceMap: true,
sassOptions: {
includePaths: [
path.resolve(__dirname, '../../node_modules'),
],
},
},
},
}, {
loader: 'sass-loader',
options: {
sourceMap: true,
includePaths: [
path.resolve(__dirname, '../../node_modules'),
],
},
}],
],
})
configBase.plugins = [
configBase.plugins = configBase.plugins.concat([
new webpack.HotModuleReplacementPlugin(),
new webpack.NoEmitOnErrorsPlugin(), // don't reload if there is an error
new BundleTracker({
path: __dirname,
filename: path.join('..', 'webpack', 'stats.json'),
}),
new ExtractTextPlugin('[name].css'),
// keeps hashes consistent between compilations, isn't needed since
// webpack 2
// new webpack.optimize.OccurrenceOrderPlugin(),
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
filename: 'vendor.bundle.js',
}),
]
extractCSS,
])
configBase.optimization = {
runtimeChunk: 'single', // enable 'runtime' chunk
splitChunks: {
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendor',
chunks: 'all',
},
},
},
}
configBase.mode = 'development'
module.exports = configBase

View file

@ -3,13 +3,21 @@
'use strict'
const configBase = require('./config.base')
const webpack = require('webpack')
const path = require('path')
const BundleTracker = require('webpack-bundle-tracker')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const extractCSS = new ExtractTextPlugin('stylesheets/[name].css')
const configBase = require('./config.base')
const extractCSS = new MiniCssExtractPlugin({
// Options similar to the same options in webpackOptions.output
// both options are optional
filename: 'stylesheets/[name].css',
chunkFilename: 'stylesheets/[id].css',
})
const postCssConfigPath = path.resolve(
path.join(__dirname, '..', '..', 'postcss.config.js'))
// This turns on the creation of map files, in addition to turning on
// sourcemaps in plugins, this MUST be specified
@ -19,43 +27,64 @@ configBase.output.filename = '[name].js'
configBase.module.rules.push({
test: /\.s[ac]ss$/,
use: extractCSS.extract({
fallback: 'style-loader',
use: [{
loader: 'css-loader',
// This should be changed to options as soon as the loader
// supports it here.
query: {
sourceMap: true,
importLoaders: 1,
},
}, {
use: [
{ loader: MiniCssExtractPlugin.loader },
{ loader: 'css-loader', options: { sourceMap: true, importLoaders: 1 } },
{
loader: 'postcss-loader',
options: { config: { path: postCssConfigPath }, sourceMap: true },
},
{
loader: 'sass-loader',
// This should be changed to options as soon as the loader
// supports it here.
query: {
options: {
sourceMap: true,
includePaths: [
path.resolve(__dirname, '../../node_modules'),
],
sassOptions: {
includePaths: [
path.resolve(__dirname, '../../node_modules'),
],
},
},
}],
}),
},
],
})
configBase.plugins = [
// Stylus compiler
configBase.module.rules.push({
test: /\.styl$/,
use: [
{ loader: MiniCssExtractPlugin.loader },
{ loader: 'css-loader', options: { sourceMap: true, importLoaders: 1 } },
{
loader: 'postcss-loader',
options: { config: { path: postCssConfigPath }, sourceMap: true },
},
{
loader: 'stylus-loader',
options: { sourceMap: true, preferPathResolver: 'webpack' },
},
],
})
configBase.plugins = configBase.plugins.concat([
new BundleTracker({
path: __dirname,
filename: path.join('..', 'webpack', 'stats.json'),
}),
extractCSS,
// keeps hashes consistent between compilations
// new webpack.optimize.OccurrenceOrderPlugin(),
new webpack.optimize.CommonsChunkPlugin({
minChunks: 3,
name: 'vendor',
filename: 'vendor.bundle.js',
}),
]
])
configBase.optimization = {
runtimeChunk: 'single', // enable 'runtime' chunk
splitChunks: {
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendor',
chunks: 'all',
},
},
},
}
configBase.mode = 'development'
module.exports = configBase

View file

@ -1,66 +1,110 @@
const path = require('path')
const webpack = require('webpack')
const BundleTracker = require('webpack-bundle-tracker')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const TerserPlugin = require('terser-webpack-plugin')
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin')
const cleanCss = require('clean-css')
const configBase = require('./config.base')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const extractCSS = new ExtractTextPlugin('stylesheets/[name]-[hash:6].css')
const extractCSS = new MiniCssExtractPlugin({
// Options similar to the same options in webpackOptions.output
// both options are optional
filename: 'stylesheets/[name]-[hash:6].css',
chunkFilename: 'stylesheets/[id]-[hash:6].css',
})
configBase.plugins = [
const postCssConfigPath = path.resolve(
path.join(__dirname, '..', '..', 'postcss.config.js'),
)
configBase.plugins = configBase.plugins.concat([
new BundleTracker({
path: __dirname,
filename: path.join('..', 'webpack', 'stats.json'),
}),
// To split all the CSS files
extractCSS,
])
// removes a lot of debugging code in React
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify('production'),
},
}),
new webpack.optimize.CommonsChunkPlugin({
minChunks: 3,
name: 'vendor',
filename: 'vendor.bundle-[hash:6].js',
}),
// minifies your code
new webpack.optimize.UglifyJsPlugin({
compressor: {
warnings: false,
},
}),
]
// Sass compiler
configBase.module.rules.push({
test: /\.s[ac]ss$/,
use: extractCSS.extract({
fallback: 'style-loader',
use: [{
loader: 'css-loader',
// This should be changed to options as soon as the loader
// supports it here.
query: {
sourceMap: true,
importLoaders: 1,
},
}, {
use: [
{ loader: MiniCssExtractPlugin.loader },
{ loader: 'css-loader', options: { importLoaders: 1 } },
{
loader: 'postcss-loader',
options: { config: { path: postCssConfigPath }, sourceMap: false },
},
{
loader: 'sass-loader',
// This should be changed to options as soon as the loader
// supports it here.
query: {
sourceMap: true,
includePaths: [
path.resolve(__dirname, '../../node_modules'),
],
options: {
sassOptions: {
includePaths: [
path.resolve(__dirname, '../../node_modules'),
],
},
},
}],
}),
},
],
})
// Stylus compiler
configBase.module.rules.push({
test: /\.styl$/,
use: [
{ loader: MiniCssExtractPlugin.loader },
{ loader: 'css-loader', options: { importLoaders: 1 } },
{
loader: 'postcss-loader',
options: { config: { path: postCssConfigPath }, sourceMap: false },
},
{ loader: 'stylus-loader', options: { preferPathResolver: 'webpack' } },
],
})
configBase.optimization = {
runtimeChunk: 'single', // enable 'runtime' chunk
splitChunks: {
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendor',
chunks: 'all',
},
},
},
minimizer: [
// we specify a custom UglifyJsPlugin here to get source maps in production
new TerserPlugin({
cache: true,
extractComments: true,
parallel: true,
terserOptions: {
ecma: 8,
// compress: true,
compress: false,
// mangle: true,
mangle: false,
output: {
comments: false,
},
},
sourceMap: false,
}),
// Related issue: https://github.com/cssnano/cssnano/issues/712
new OptimizeCSSAssetsPlugin({
cssProcessor: cleanCss,
cssProcessorPluginOptions: {
preset: ['default', { discardComments: { removeAll: true } }],
},
canPrint: true,
}),
],
}
configBase.mode = 'production'
// Override font naming in production
configBase.module.rules[0].use[0].options.name = 'fonts/[name]-[hash:6].[ext]'
configBase.module.rules[1].use[0].options.name = 'fonts/[name]-[hash:6].[ext]'

View file

@ -1,7 +1,8 @@
/* eslint global-require: "off", import/no-extraneous-dependencies: "off" */
// Include gulp
const gulp = require('gulp')
const gutil = require('gulp-util')
const PluginError = require('plugin-error')
const fancyLog = require('fancy-log')
const webpackStream = require('webpack-stream')
const webpack = require('webpack')
const WebpackDevServer = require('webpack-dev-server')
@ -11,6 +12,8 @@ const del = require('del')
// const bundleHelper = require('./frontend/src/js/loader/bundlehelper')
const eslint = require('gulp-eslint')
const sourceGlob = ['frontend/src/**/*.js']
// const htmlReplaceSkeleton = () =>
// gulp.src('frontend/src/index.html')
// .pipe(htmlreplace({
@ -25,49 +28,78 @@ const eslint = require('gulp-eslint')
gulp.task('clean', () => del(['./frontend/dist/**/*']))
// Lint Task
gulp.task('lint', () => gulp.src(['frontend/src/**/*.js'])
// eslint() attaches the lint output to the "eslint" property
// of the file object so it can be used by other modules.
.pipe(eslint())
// eslint.format() outputs the lint results to the console.
// Alternatively use eslint.formatEach() (see Docs).
.pipe(eslint.format())
// To have the process exit with an error code (1) on
// lint error, return the stream and pipe to failAfterError last.
.pipe(eslint.failAfterError()))
if (process.argv.length < 4) {
gulp.task('lint', () => gulp.src(sourceGlob)
// eslint() attaches the lint output to the "eslint" property
// of the file object so it can be used by other modules.
.pipe(eslint())
// eslint.format() outputs the lint results to the console.
// Alternatively use eslint.formatEach() (see Docs).
.pipe(eslint.format())
// To have the process exit with an error code (1) on
// lint error, return the stream and pipe to failAfterError last.
.pipe(eslint.failAfterError()))
} else if (process.argv[3] === '-n') {
const passedFiles = process.argv[4].split('\n')
gulp.task('lint', () => gulp.src(passedFiles)
// eslint() attaches the lint output to the "eslint" property
// of the file object so it can be used by other modules.
.pipe(eslint())
// eslint.format() outputs the lint results to the console.
// Alternatively use eslint.formatEach() (see Docs).
.pipe(eslint.format())
// To have the process exit with an error code (1) on
// lint error, return the stream and pipe to failAfterError last.
.pipe(eslint.failAfterError()))
}
gulp.task('webpack-prod', ['lint'], () => gulp.src('')
.pipe(webpackStream(require('./frontend/webpack/config.prod'), webpack))
.pipe(gulp.dest('frontend/dist/assets/')))
gulp.task('clean-lint', gulp.parallel(['clean', 'lint']))
gulp.task('webpack-dev', ['lint'], () => gulp.src('')
.pipe(webpackStream(require('./frontend/webpack/config.dev'), webpack))
.pipe(gulp.dest('frontend/dist/assets/')))
gulp.task('webpack-prod', gulp.series('clean-lint', (done) => {
gulp.src(sourceGlob)
.pipe(webpackStream(require('./frontend/webpack/config.prod'), webpack))
.pipe(gulp.dest('frontend/dist/assets/'))
done()
}))
gulp.task('build', ['clean', 'webpack-prod'])
gulp.task('build-dev', ['clean', 'webpack-dev'])
gulp.task('webpack-dev', gulp.series(['clean-lint'], (done) => {
gulp.src(sourceGlob)
.pipe(webpackStream(require('./frontend/webpack/config.dev'), webpack))
.pipe(gulp.dest('frontend/dist/assets/'))
done()
}))
gulp.task('webpack-dev-server', ['clean'], () => {
gulp.task('build', gulp.series(['webpack-prod']))
gulp.task('build-dev', gulp.series(['clean', 'webpack-dev']))
gulp.task('webpack-dev-server', gulp.series(['clean'], (done) => {
const config = require('./frontend/webpack/config.dev-server')
const compiler = webpack(config)
const server = new WebpackDevServer(compiler, {
hot: true,
inline: true,
port: 3000,
historyApiFallback: true,
contentBase: path.join(__dirname, 'frontend', 'src'),
publicPath: '/static/assets/',
stats: {
colors: true,
},
// https://github.com/webpack/webpack-dev-server/issues/533#issuecomment-296438189
// FIXME: https://github.com/webpack/webpack-dev-server/issues/533#issuecomment-298202657
// https://github.com/webpack/webpack-dev-server/issues/533#issuecomment-465222472
disableHostCheck: true,
headers: {
'Access-Control-Allow-Origin': '*',
},
})
server.listen(3000, '0.0.0.0', (err) => {
if (err) throw new gutil.PluginError('webpack-dev-server', err)
if (err) throw new PluginError('webpack-dev-server', err)
// Server listening
gutil.log('[webpack-dev-server]', 'http://localhost:3000/')
fancyLog('[webpack-dev-server]', 'http://localhost:3000/')
})
})
done()
}))
gulp.task('default', ['clean', 'lint'], () => {
// This will only run if the lint task is successful...
})
gulp.task('default', gulp.series('clean-lint'))

View file

@ -5,22 +5,37 @@
"main": "index.js",
"dependencies": {},
"devDependencies": {
"awesome-bootstrap-checkbox": "git+https://github.com/flatlogic/awesome-bootstrap-checkbox#bump-to-bootstrap4",
"babel-core": "^6.26.3",
"@babel/core": "^7.7.4",
"@babel/plugin-proposal-class-properties": "^7.7.4",
"@babel/plugin-proposal-decorators": "^7.7.4",
"@babel/plugin-proposal-do-expressions": "^7.7.4",
"@babel/plugin-proposal-export-default-from": "^7.7.4",
"@babel/plugin-proposal-export-namespace-from": "^7.7.4",
"@babel/plugin-proposal-function-bind": "^7.7.4",
"@babel/plugin-proposal-function-sent": "^7.7.4",
"@babel/plugin-proposal-json-strings": "^7.7.4",
"@babel/plugin-proposal-logical-assignment-operators": "^7.7.4",
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.7.4",
"@babel/plugin-proposal-numeric-separator": "^7.7.4",
"@babel/plugin-proposal-optional-chaining": "^7.7.4",
"@babel/plugin-proposal-pipeline-operator": "^7.7.4",
"@babel/plugin-proposal-throw-expressions": "^7.7.4",
"@babel/plugin-syntax-dynamic-import": "^7.7.4",
"@babel/plugin-syntax-import-meta": "^7.7.4",
"@babel/plugin-transform-runtime": "^7.7.4",
"@babel/preset-env": "^7.7.4",
"@babel/runtime": "^7.7.4",
"autoprefixer": "^9.7.2",
"babel-eslint": "^10.0.3",
"babel-loader": "^8.0.6",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-preset-es2015": "^6.24.1",
"babel-preset-es2017": "^6.24.1",
"babel-preset-stage-0": "^6.24.1",
"babel-preset-stage-2": "^6.24.1",
"bootstrap": "git+https://github.com/twbs/bootstrap.git#v4-dev",
"bootstrap": "^4.4.0",
"css-loader": "^3.2.0",
"eslint": "^6.7.1",
"eslint-config-airbnb-base": "^14.0.0",
"eslint-plugin-import": "^2.18.2",
"exports-loader": "^0.7.0",
"extract-text-webpack-plugin": "^3.0.2",
"fancy-log": "^1.3.3",
"file-loader": "^5.0.2",
"font-awesome": "^4.7.0",
"gulp": "^4.0.2",
@ -29,6 +44,7 @@
"install": "^0.13.0",
"jquery": "^3.4.1",
"json-loader": "^0.5.7",
"mini-css-extract-plugin": "^0.8.0",
"moment": "^2.24.0",
"moment-timezone": "^0.5.27",
"mutation-observer": "^1.0.3",
@ -36,6 +52,8 @@
"npm": "^6.13.1",
"npm-check-updates": "^3.2.2",
"pen": "git+https://github.com/sofish/pen.git#master",
"plugin-error": "^1.0.1",
"postcss-loader": "^3.0.0",
"raw-loader": "^4.0.0",
"resolve-url-loader": "^3.1.1",
"sass-loader": "^8.0.0",

5
postcss.config.js Normal file
View file

@ -0,0 +1,5 @@
module.exports = {
plugins: {
autoprefixer: {},
},
}