Intial commit

This commit is contained in:
Tony Air 2018-02-05 18:11:01 +07:00
parent 3d354656da
commit 6a33a8583b
27 changed files with 1049 additions and 0 deletions

18
.gitignore vendored Normal file
View File

@ -0,0 +1,18 @@
# START Do not modify the lines between here and #END, they will be regenerated by GitIgnoreEditor
/betternavigator
/cms
/debugbar
/framework
/ideannotator
/redirectedurls
/reports
/silverstripe-scaled-uploads
/silverstripe-version-truncator
/siteconfig
# END of GitIgnoreEditor
/node_modules
/composer.lock
/yarn.lock
/vendor
/site/dist

12
browserconfig.xml Normal file
View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<browserconfig>
<msapplication>
<tile>
<square70x70logo src="/site/dist/icons/mstile-70x70.png"/>
<square150x150logo src="/site/dist/icons/mstile-150x150.png"/>
<wide310x150logo src="/site/dist/icons/mstile-310x150.png"/>
<square310x310logo src="/site/dist/icons/mstile-310x310.png"/>
<TileColor>#000</TileColor>
</tile>
</msapplication>
</browserconfig>

10
cache.appcache Executable file
View File

@ -0,0 +1,10 @@
CACHE MANIFEST
FALLBACK:
/
/site/dist/css/app.css
/site/dist/img/logo.png
/site/dist/img/fonts/fontawesome-webfont.woff2?v=4.7.0
/site/dist/img/fonts/fontawesome-webfont.woff?v=4.7.0
/site/dist/img/fonts/fontawesome-webfont.ttf?v=4.7.0
/site/dist/js/app.js

32
composer.json Executable file
View File

@ -0,0 +1,32 @@
{
"name": "silverstripe/installer",
"description": "The SilverStripe webpack boilerplate",
"require": {
"php": ">=5.5.0",
"silverstripe/cms": "*",
"silverstripe/framework": "3.7.x-dev",
"silverstripe/redirectedurls": "*",
"axllent/silverstripe-scaled-uploads": "*",
"jonom/silverstripe-betternavigator": "*",
"axllent/silverstripe-version-truncator": "*"
},
"require-dev": {
"phpunit/PHPUnit": "~3.7",
"gdmedia/ss-auto-git-ignore": "^1.0",
"axyr/silverstripe-ideannotator": "dev-master",
"lekoala/silverstripe-debugbar": "^1.0"
},
"scripts": {
"post-update-cmd": "GDM\\SSAutoGitIgnore\\UpdateScript::Go"
},
"config": {
"process-timeout": 600,
"discard-changes": true
},
"extra": {
"branch-alias": {
"3.x-dev": "3.6.x-dev"
}
},
"minimum-stability": "dev"
}

11
humans.txt Executable file
View File

@ -0,0 +1,11 @@
/* AUTHOR */
Name:
/* TEAM */
Site: https://bla-bla.com/
/* SITE */
Doctype: HTML5
IDE: PHPStorm, Sublime Text, Photoshop, Transmit
Framework: SilverStripe
Language: English

49
manifest.json Normal file
View File

@ -0,0 +1,49 @@
{
"name": "SilverStripe",
"short_name": "SilverStripe website",
"description": "",
"dir": "auto",
"lang": "en-US",
"display": "standalone",
"orientation": "any",
"start_url": "/?homescreen=1",
"theme_color": "#000000",
"background_color": "#000000",
"icons": [{
"src": "/dist/icons/android-chrome-36x36.png",
"sizes": "36x36",
"type": "image/png"
}, {
"src": "/dist/icons/android-chrome-48x48.png",
"sizes": "48x48",
"type": "image/png"
}, {
"src": "/dist/icons/android-chrome-72x72.png",
"sizes": "72x72",
"type": "image/png"
}, {
"src": "/dist/icons/android-chrome-96x96.png",
"sizes": "96x96",
"type": "image/png"
}, {
"src": "/dist/icons/android-chrome-144x144.png",
"sizes": "144x144",
"type": "image/png"
}, {
"src": "/dist/icons/android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png"
}, {
"src": "/dist/icons/android-chrome-256x256.png",
"sizes": "256x256",
"type": "image/png"
}, {
"src": "/dist/icons/android-chrome-384x384.png",
"sizes": "384x384",
"type": "image/png"
}, {
"src": "/dist/icons/android-chrome-512x512.png",
"sizes": "512x512",
"type": "image/png"
}]
}

110
package.json Executable file
View File

@ -0,0 +1,110 @@
{
"name": "ss-webpack-boilerplate",
"version": "1.0.0",
"description": "Lets you create SilverStripe faster",
"author": "Tony Air <tony@twma.pro>",
"license": "MIT",
"private": false,
"engines": {
"yarn": ">= 1.0.0"
},
"scripts": {
"start": "cross-env NODE_ENV=development webpack-dev-server -d --config webpack.config.dev.js",
"dash": "cross-env NODE_ENV=development webpack-dashboard -- webpack-dev-server --config webpack.config.dev.js",
"prebuild": "rimraf build",
"build": "cross-env NODE_ENV=production webpack -p --config webpack.config.prod.js --progress"
},
"dependencies": {
"bootstrap": "twbs/bootstrap#>= 3.1.0",
"favicons-webpack-plugin": "^0.0.7",
"jquery": "^3.3.1",
"js-yaml": "^3.10.0",
"popper": "^1.0.1",
"popper.js": "^1.12.9"
},
"devDependencies": {
"exports-loader": "^0.7.0",
"favicons-webpack-plugin": "^0.0.7",
"@silverstripe/eslint-config": "0.0.2",
"autoprefixer": "^7.2.5",
"babel-core": "^6.26.0",
"babel-loader": "^7.1.2",
"babel-plugin-transform-react-jsx": "^6.24.1",
"babel-preset-es2015": "^6.24.1",
"babel-preset-react": "^6.24.1",
"babel-preset-stage-2": "^6.24.1",
"browser-sync": "^2.23.6",
"browser-sync-webpack-plugin": "^1.2.0",
"copy-webpack-plugin": "^4.3.1",
"copyfiles": "^1.2.0",
"cross-env": "^5.1.3",
"css-loader": "^0.28.9",
"extract-text-webpack-plugin": "^3.0.2",
"file-loader": "^1.1.5",
"html-webpack-plugin": "^2.30.1",
"laravel-mix": "^1.0",
"lost": "^8.2.0",
"node-sass": "^4.6.1",
"optimize-css-assets-webpack-plugin": "^3.2.0",
"postcss-loader": "^2.0.10",
"react": "^16.2.0",
"react-dom": "^16.2.0",
"react-hot-loader": "^3.1.3",
"redux": "^3.7.2",
"redux-devtools-extension": "^2.13.2",
"resolve-url-loader": "^2.2.1",
"rimraf": "^2.6.2",
"sass-loader": "^6.0.6",
"script-ext-html-webpack-plugin": "^1.8.8",
"style-loader": "^0.19.0",
"svg-url-loader": "^2.3.1",
"uglifyjs-webpack-plugin": "^1.1.6",
"url-loader": "^0.6.2",
"webpack": "^3.8.1",
"webpack-dashboard": "^1.1.1",
"webpack-dev-server": "^2.11.1",
"webpack-manifest-plugin": "^1.3.2",
"webpack-merge": "^4.1.1",
"worker-loader": "^1.1.0"
},
"stylelint": {
"rules": {
"block-no-empty": null,
"color-no-invalid-hex": true,
"comment-empty-line-before": [
"always", {
"ignore": [
"stylelint-commands",
"after-comment"
]
}
],
"declaration-colon-space-after": "always",
"indentation": [
4, {
"except": [
"value"
]
}
],
"max-empty-lines": 2,
"rule-empty-line-before": [
"always", {
"except": [
"first-nested"
],
"ignore": [
"after-comment"
]
}
],
"unit-whitelist": [
"em",
"rem",
"%",
"s",
"px"
]
}
}
}

25
phpcs.xml.dist Executable file
View File

@ -0,0 +1,25 @@
<?xml version="1.0"?>
<ruleset name="SS3">
<description>Coding standard for SilverStripe 3.x</description>
<!-- Don't sniff third party libraries -->
<exclude-pattern>*/vendor/*</exclude-pattern>
<exclude-pattern>*/thirdparty/*</exclude-pattern>
<exclude-pattern>*/node_modules/*</exclude-pattern>
<!-- Show progress and output sniff names on violation, and add colours -->
<arg value="sp"/>
<arg name="colors"/>
<!-- Use PSR-2 as a base standard -->
<rule ref="PSR2">
<!-- Allow classes to not declare a namespace -->
<exclude name="PSR1.Classes.ClassDeclaration.MissingNamespace"/>
<!-- Allow underscores in class names -->
<exclude name="Squiz.Classes.ValidClassName.NotCamelCaps"/>
<!-- Allow non camel cased method names -->
<exclude name="PSR1.Methods.CamelCapsMethodName.NotCamelCaps"/>
</rule>
</ruleset>

18
phpunit.xml Executable file
View File

@ -0,0 +1,18 @@
<phpunit bootstrap="framework/tests/bootstrap.php" colors="true">
<testsuite name="Default">
<directory>cms/tests</directory>
<directory>framework/tests</directory>
</testsuite>
<listeners>
<listener class="SS_TestListener" file="framework/dev/TestListener.php" />
</listeners>
<groups>
<exclude>
<group>sanitychecks</group>
</exclude>
</groups>
</phpunit>

7
robots.txt Executable file
View File

@ -0,0 +1,7 @@
User-agent: *
Allow: /
Crawl-delay: 10
Disallow: /admin
Disallow: /Security
Sitemap: https://www.bla-bla.org/sitemap.xml
Host: https://www.bla-bla.org

View File

@ -0,0 +1,90 @@
<?php
/**
* Directs assets requests to Webpack server or to static files
*/
class WebpackTemplateProvider extends Object implements TemplateGlobalProvider
{
/**
* @return array
*/
public static function get_template_global_variables()
{
return [
'WebpackDevServer' => 'isActive',
'WebpackCSS' => 'loadCSS',
'WebpackJS' => 'loadJS',
];
}
/**
* @var int port number
*/
private static $port = 3000;
/**
* @var string host name
*/
private static $hostname = 'localhost';
/**
* @var string assets static files directory
*/
private static $distDir = 'site/dist';
/**
* Load CSS file
* @param $path
*/
public static function loadCSS($path)
{
if (!self::isActive()) {
Requirements::css(self::_toPublicPath($path));
}
}
/**
* Load JS file
* @param $path
*/
public static function loadJS($path)
{
$path = self::isActive() ?
self::_toDevServerPath($path) :
self::_toPublicPath($path);
Requirements::javascript($path);
}
/**
* Checks if dev mode is enabled and if webpack server is online
* @return bool
*/
public static function isActive()
{
$class = __CLASS__;
return Director::isDev() && !!@fsockopen(
$class::config()->get('hostname'),
$class::config()->get('port')
);
}
protected static function _toDevServerPath($path)
{
$class = __CLASS__;
return sprintf(
'http://%s:%s/%s',
$class::config()->get('hostname'),
$class::config()->get('port'),
$path
);
}
protected static function _toPublicPath($path)
{
$class = __CLASS__;
return $class::config()->get('distDir') . '/' . $path;
}
}

10
site/_config/webpack.yml Normal file
View File

@ -0,0 +1,10 @@
# that's important to place this file into /site/_config/webpack.yml
# with all configuration variables presented
# Cuz WebPack compiling script use it to set configuration
WebpackTemplateProvider:
dist: site/dist
hostname: localhost
port: "3000"
pages: site/src/js/types
src: site/src

View File

@ -0,0 +1,10 @@
# that's important to place this file into /site/_config/webpack.yml
# with all configuration variables presented
# Cuz WebPack compiling script use it to set configuration
WebpackTemplateProvider:
dist: site/dist
hostname: localhost
port: "3000"
pages: site/src/js/types
src: site/src

BIN
site/src/favicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

View File

@ -0,0 +1,19 @@
/**
* Just an example component
*/
import $ from "jquery";
const SpinnerUI = (($) => {
class SpinnerUI {
static show(callback) {
$("#PageLoading").show(0, callback);
}
static hide(callback) {
$("#PageLoading").hide("slow", callback);
}
}
return SpinnerUI;
})($);
export default SpinnerUI;

8
site/src/js/_events.js Normal file
View File

@ -0,0 +1,8 @@
/**
* Add your global events here
*/
module.exports = {
AJAX: "ajax-load",
LOADED: "load"
};

View File

@ -0,0 +1,88 @@
import $ from "jquery";
const TypePage = (($) => {
// Constants
const NAME = "TypePage";
//const DATA_KEY = "pageUI." + NAME;
const Events = require("./_events");
class TypePage {
// Static methods
static init() {
console.log("Initializing: " + NAME);
}
static destroy() {
console.log("Destroying: " + NAME);
}
/**
* jQuery extension functions
// Constructor
constructor(element) {
console.log("Constructing: " + NAME + " elements");
this._element = element;
}
// Public methods
dispose() {
console.log("Disposing: " + NAME + " elements");
$.removeData(this._element, DATA_KEY);
this._element = null;
}
static _jQueryInterface() {
return this.each(function () {
// attach functionality to element
const $element = $(this);
let data = $element.data(DATA_KEY);
if (!data) {
data = new TypePage(this);
$element.data(DATA_KEY, data);
}
})
}
*/
}
$(window).on(Events.AJAX + " " + Events.LOADED, function() {
TypePage.init();
});
// JQuery extension functions
/*$.fn[NAME] = TypePage._jQueryInterface;
$.fn[NAME].Constructor = TypePage;
$.fn[NAME].noConflict = function () {
$.fn[NAME] = JQUERY_NO_CONFLICT;
return TypePage._jQueryInterface;
};*/
return TypePage;
})($);
export default TypePage;
/*
import $ from 'jquery';
(function (G) {
G.initPulsePage = function () {
G.destroyPulsePage();
};
G.destroyPulsePage = function () {};
$(window).on("ajax-content-loaded", function () {
G.initPulsePage();
});
$(document).ready(function () {
G.initPulsePage();
});
}(this));*/

38
site/src/js/app.js Normal file
View File

@ -0,0 +1,38 @@
// import images
function importAll(r) {
return r.keys().map(r);
}
const images = importAll(require.context("../img/", false, /\.(png|jpe?g|svg)$/));
import "../scss/app.scss";
// import Bootstrap
import Popper from "popper.js";
window.Popper = Popper;
import "bootstrap/js/dist/util";
import "bootstrap/js/dist/alert";
import "bootstrap/js/dist/button";
import "bootstrap/js/dist/carousel";
import "bootstrap/js/dist/collapse";
import "bootstrap/js/dist/dropdown";
import "bootstrap/js/dist/modal";
import "bootstrap/js/dist/tooltip";
import "bootstrap/js/dist/popover";
import "bootstrap/js/dist/scrollspy";
import "bootstrap/js/dist/tab";
//
// import your custom UI components
import "./main.js";
// TODO: hot module update
/*const Events = require("./_events");
if (module.hot) {
module.hot.accept();
module.hot.addStatusHandler(status => {
if(status === "apply"){
$(window).trigger(Events.AJAX);
}
});
}*/

38
site/src/js/main.js Normal file
View File

@ -0,0 +1,38 @@
import $ from "jquery";
import Events from "./_events";
// import an example component
import Spinner from "./_components/_spinner";
const MainUI = (($) => {
// Constants
const NAME = "MainUI";
class MainUI {
// Static methods
static init() {
this.destroy();
console.log("Initializing: " + NAME);
Spinner.hide(function() {
$("body").addClass("loaded");
});
}
static destroy() {
console.log("Destroying: " + NAME);
Spinner.show(function() {
$("body").removeClass("loaded");
});
}
}
$(window).on(Events.AJAX + " " + Events.LOADED, function() {
MainUI.init();
});
return MainUI;
})($);
export default MainUI;

View File

@ -0,0 +1,7 @@
/**
* Your custom style
*/
html,body {
background:#000;
}

View File

@ -0,0 +1,10 @@
/*
* Your custom variables
*/
// bootstrap minify bugfix:
$navbar-dark-toggler-icon-bg: none;
$navbar-light-toggler-icon-bg: none;
// IE > 9
$enable-flex: true;

42
site/src/scss/app.scss Normal file
View File

@ -0,0 +1,42 @@
// Your custom variables
@import "variables";
// Bootstrap basics
@import "../../../node_modules/bootstrap/scss/functions";
@import "../../../node_modules/bootstrap/scss/variables";
@import "../../../node_modules/bootstrap/scss/mixins";
@import "../../../node_modules/bootstrap/scss/root";
@import "../../../node_modules/bootstrap/scss/reboot";
@import "../../../node_modules/bootstrap/scss/type";
@import "../../../node_modules/bootstrap/scss/images";
@import "../../../node_modules/bootstrap/scss/code";
@import "../../../node_modules/bootstrap/scss/grid";
@import "../../../node_modules/bootstrap/scss/tables";
@import "../../../node_modules/bootstrap/scss/forms";
@import "../../../node_modules/bootstrap/scss/buttons";
@import "../../../node_modules/bootstrap/scss/transitions";
@import "../../../node_modules/bootstrap/scss/dropdown";
@import "../../../node_modules/bootstrap/scss/button-group";
@import "../../../node_modules/bootstrap/scss/input-group";
@import "../../../node_modules/bootstrap/scss/custom-forms";
@import "../../../node_modules/bootstrap/scss/nav";
@import "../../../node_modules/bootstrap/scss/navbar";
@import "../../../node_modules/bootstrap/scss/card";
@import "../../../node_modules/bootstrap/scss/breadcrumb";
@import "../../../node_modules/bootstrap/scss/pagination";
@import "../../../node_modules/bootstrap/scss/badge";
@import "../../../node_modules/bootstrap/scss/jumbotron";
@import "../../../node_modules/bootstrap/scss/alert";
@import "../../../node_modules/bootstrap/scss/progress";
@import "../../../node_modules/bootstrap/scss/media";
@import "../../../node_modules/bootstrap/scss/list-group";
@import "../../../node_modules/bootstrap/scss/close";
@import "../../../node_modules/bootstrap/scss/modal";
@import "../../../node_modules/bootstrap/scss/tooltip";
@import "../../../node_modules/bootstrap/scss/popover";
@import "../../../node_modules/bootstrap/scss/carousel";
@import "../../../node_modules/bootstrap/scss/utilities";
@import "../../../node_modules/bootstrap/scss/print";
// Your custom UI
@import "layout";

64
site/templates/Page.ss Normal file
View File

@ -0,0 +1,64 @@
<!DOCTYPE html>
<html lang="$ContentLocale.ATT" dir="$i18nScriptDirection.ATT">
<%-- manifest="/cache.appcache" --%>
<head>
$MetaTags
<meta name="theme-color" content="#000000" />
<meta name="msapplication-navbutton-color" content="#000000" />
<meta name="apple-mobile-web-app-status-bar-style" content="#000000" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="mobile-web-app-capable" content="yes" />
<link rel="author" type="text/plain" href="{$AbsoluteBaseURL}humans.txt" />
<link rel="sitemap" type="application/xml" title="Sitemap" href="{$AbsoluteBaseURL}sitemap.xml" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link rel="preconnect" href="https://maps.google.com" />
<link rel="preconnect" href="https://ajax.googleapis.com" />
<link rel="preconnect" href="https://csi.gstatic.com" />
<link rel="preconnect" href="https://maps.googleapis.com" />
<link rel="preconnect" href="https://www.youtube.com">
<link rel="preconnect" href="https://i.ytimg.com">
<link rel="preconnect" href="https://i9.ytimg.com">
<link rel="preconnect" href="https://s.ytimg.com">
<% base_tag %>
<link rel="shortcut icon" type="image/x-icon" href="{$AbsoluteBaseURL}{$Project}/site/dist/icons/favicon.ico" />
<link rel="icon" sizes="144x144" type="image/png" href="{$AbsoluteBaseURL}{$Project}/site/dist/icons/android-chrome-144x144.png" />
<link rel="apple-touch-icon" href="{$AbsoluteBaseURL}{$Project}/site/dist/icons/apple-touch-icon.png" />
<link rel="apple-touch-icon-precomposed" href="{$AbsoluteBaseURL}{$Project}/site/dist/icons/apple-touch-icon-precomposed.png" />
<link rel="manifest" href="/manifest.webmanifest" />
<meta name="application-name" content="{$SiteConfig.Title}" />
<meta name="msapplication-TileImage" content="{$AbsoluteBaseURL}{$Project}/site/dist/icons/mstile-144x144.png" />
<meta name="msapplication-TileColor" content="#2F98F1" />
<meta content="yes" name="apple-mobile-web-app-capable" />
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width,user-scalable=no,initial-scale=1,maximum-scale=1" />
</head>
<body oncontextmenu="return false;">
<header>
</header>
<main data-ajax-region="LayoutAjax">
$Layout
</main>
<footer>
</footer>
<div class="hidden-print">
$BetterNavigator
</div>
$WebpackJS('app.js')
$WebpackCSS('app.css')
</body>
</html>

122
webpack.config.common.js Executable file
View File

@ -0,0 +1,122 @@
const path = require("path");
const webpack = require("webpack");
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const ManifestPlugin = require("webpack-manifest-plugin");
const conf = require("./webpack.configuration");
const isProduction = process.env.NODE_ENV === "production";
const jsScripts = {
app: path.join(conf.SRC, "js/app.js"),
};
const _getAllFilesFromFolder = function(dir) {
let filesystem = require("fs");
let results = [];
filesystem.readdirSync(dir).forEach(function(file) {
file = dir + "/" + file;
let stat = filesystem.statSync(file);
if (stat && stat.isDirectory()) {
results = results.concat(_getAllFilesFromFolder(file))
} else results.push(file);
});
return results;
};
// add page specific scripts
const pageScripts = _getAllFilesFromFolder(conf.PAGES);
pageScripts.forEach((file) => {
jsScripts[path.basename(file, ".js")] = file;
});
module.exports = {
entry: jsScripts,
devtool: "source-map",
externals: {
"custom-select": "CustomSelect",
"ui-progress-button": "UIProgressButton"
},
module: {
rules: [{
test: /\.jsx?$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: [
["es2015", {
modules: false
}],
["stage-2"]
],
plugins: [
["transform-react-jsx"],
["react-hot-loader/babel"],
]
},
}
}, {
test: /\.(png|jpg|gif|svg)$/,
loader: "file-loader",
options: {
name: "img/[name].[ext]",
}
}, {
test: /\.eot(\?v=\d+.\d+.\d+)?$/,
use: {
loader: "file-loader",
options: {
name: "fonts/[name].[ext]"
}
}
}, {
test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
use: {
loader: "url-loader",
options: {
name: "fonts/[name].[ext]",
limit: 10000,
mimetype: "application/font-woff"
}
}
}, {
test: /\.[ot]tf(\?v=\d+.\d+.\d+)?$/,
use: {
loader: "url-loader",
options: {
name: "fonts/[name].[ext]",
limit: 10000,
mimetype: "application/octet-stream"
}
}
}, {
test: /\.worker\.js$/,
use: {
loader: "worker-loader"
}
}]
},
plugins: [
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery",
"window.jQuery": "jquery",
Popper: ["popper.js", "default"],
Util: "exports-loader?Util!bootstrap/js/dist/util",
Alert: "exports-loader?Alert!bootstrap/js/dist/alert",
Button: "exports-loader?Button!bootstrap/js/dist/button",
Carousel: "exports-loader?Carousel!bootstrap/js/dist/carousel",
Collapse: "exports-loader?Collapse!bootstrap/js/dist/collapse",
Dropdown: "exports-loader?Dropdown!bootstrap/js/dist/dropdown",
Modal: "exports-loader?Modal!bootstrap/js/dist/modal",
Tooltip: "exports-loader?Tooltip!bootstrap/js/dist/tooltip",
Popover: "exports-loader?Popover!bootstrap/js/dist/popover",
Scrollspy: "exports-loader?Scrollspy!bootstrap/js/dist/scrollspy",
Tab: "exports-loader?Tab!bootstrap/js/dist/tab",
})
],
};

97
webpack.config.dev.js Executable file
View File

@ -0,0 +1,97 @@
const autoprefixer = require('autoprefixer');
const webpack = require('webpack');
const merge = require('webpack-merge');
const common = require('./webpack.config.common.js');
const conf = require('./webpack.configuration');
const IP = process.env.IP || conf.HOSTNAME;
const PORT = process.env.PORT || conf.PORT;
const config = merge.strategy({
entry: 'prepend'
})(common, {
entry: {
app: [
'react-hot-loader/patch',
'webpack-dev-server/client?http://' + conf.HOSTNAME + ':' + conf.PORT + '/',
'webpack/hot/only-dev-server',
],
main: [
'webpack-dev-server/client?http://' + conf.HOSTNAME + ':' + conf.PORT + '/',
'webpack/hot/only-dev-server',
],
},
output: {
path: conf.BUILD,
filename: '[name].js',
// necessary for HMR to know where to load the hot update chunks
publicPath: 'http://' + conf.HOSTNAME + ':' + conf.PORT + '/'
},
module: {
rules: [{
test: /\.scss$/,
use: [{
loader: 'style-loader',
options: {
sourceMap: true
}
}, {
loader: 'css-loader',
options: {
sourceMap: true
}
}, {
loader: 'postcss-loader',
options: {
sourceMap: true,
plugins: [
autoprefixer({
// If we want to use the same browser list for more tools
// this list should be moved to package.json
// https://evilmartians.com/chronicles/autoprefixer-7-browserslist-2-released
browsers: [
'ie >= 11',
'ie_mob >= 11',
'Safari >= 10',
'Android >= 4.4',
'Chrome >= 44', // Retail
'Samsung >= 4'
]
}),
// http://lostgrid.org/docs.html
require('lost')
]
}
}, {
loader: 'sass-loader',
options: {
sourceMap: true
}
}, ]
}, ]
},
plugins: [
new webpack.NamedModulesPlugin(),
new webpack.HotModuleReplacementPlugin(),
new webpack.NoEmitOnErrorsPlugin(),
],
devServer: {
host: IP,
port: PORT,
historyApiFallback: true,
hot: true,
overlay: {
warnings: true,
errors: true
},
headers: {
'Access-Control-Allow-Origin': '*'
}
},
});
module.exports = config;

102
webpack.config.prod.js Executable file
View File

@ -0,0 +1,102 @@
const path = require('path');
const autoprefixer = require('autoprefixer');
const webpack = require('webpack');
const merge = require('webpack-merge');
const common = require('./webpack.config.common.js');
const OptimizeCSSAssets = require('optimize-css-assets-webpack-plugin');
const conf = require('./webpack.configuration');
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const FaviconsWebpackPlugin = require("favicons-webpack-plugin");
const fs = require("fs");
const yaml = require("js-yaml");
const confYML = yaml.safeLoad(fs.readFileSync(path.join(__dirname, "site/_config/webpack.yml"), "utf8"));
module.exports = merge(common, {
output: {
path: conf.BUILD,
filename: '[name].js',
publicPath: confYML.WebpackTemplateProvider.dist + '/',
},
module: {
rules: [{
test: /\.scss$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: [{
loader: 'css-loader',
options: {
sourceMap: true
}
}, {
loader: 'postcss-loader',
options: {
sourceMap: true,
plugins: [
autoprefixer({
// If we want to use the same browser list for more tools
// this list should be moved to package.json
// https://evilmartians.com/chronicles/autoprefixer-7-browserslist-2-released
browsers: [
'ie >= 11',
'ie_mob >= 11',
'Safari >= 10',
'Android >= 4.4',
'Chrome >= 44', // Retail
'Samsung >= 4'
]
}),
// http://lostgrid.org/docs.html
require('lost')
]
}
}, {
loader: 'resolve-url-loader'
}, {
loader: 'sass-loader',
options: {
sourceMap: true
}
}, ]
})
}, ]
},
plugins: [
new webpack.DefinePlugin({
'process.env': {
'NODE_ENV': JSON.stringify('production')
}
}),
new webpack.optimize.ModuleConcatenationPlugin(),
new webpack.optimize.UglifyJsPlugin({
sourceMap: true,
comments: false
}),
new ExtractTextPlugin({
filename: '[name].css',
allChunks: true
}),
new OptimizeCSSAssets(),
new FaviconsWebpackPlugin({
logo: conf.SRC + '/favicon.png',
prefix: '/icons/',
statsFilename: confYML.WebpackTemplateProvider.dist + '/icons/iconstats.json',
icons: {
android: true,
appleIcon: true,
appleStartup: true,
coast: true,
favicons: true,
firefox: true,
opengraph: true,
twitter: true,
yandex: true,
windows: true
}
}),
],
});

12
webpack.configuration.js Executable file
View File

@ -0,0 +1,12 @@
const path = require("path");
const fs = require("fs");
const yaml = require("js-yaml");
const conf = yaml.safeLoad(fs.readFileSync(path.join(__dirname, "site/_config/webpack.yml"), "utf8"));
module.exports = {
SRC: path.join(__dirname, conf.WebpackTemplateProvider.src),
BUILD: path.join(__dirname, conf.WebpackTemplateProvider.dist),
PAGES: path.join(__dirname, conf.WebpackTemplateProvider.pages),
HOSTNAME: conf.WebpackTemplateProvider.hostname,
PORT: conf.WebpackTemplateProvider.port
};