feature(webpack) split config to: js, html and css

This commit is contained in:
coderaiser 2018-04-10 18:29:52 +03:00
parent 3b17a16217
commit 1e716ef64f
5 changed files with 220 additions and 171 deletions

72
.webpack/css.js Normal file
View file

@ -0,0 +1,72 @@
'use strict';
const fs = require('fs');
const {
basename,
extname,
join,
} = require('path');
const {env} = process;
const isDev = env.NODE_ENV === 'development';
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const extractCSS = (a) => new ExtractTextPlugin(`${a}.css`);
const extractMain = extractCSS('[name]');
const cssNames = [
'nojs',
'view',
'config',
...getCSSList('columns'),
];
const cssPlugins = cssNames.map(extractCSS);
const plugins = [
...cssPlugins,
extractMain,
];
const rules = [{
test: /\.css$/,
exclude: /css\/(nojs|view|config|columns.*)\.css/,
use: extractMain.extract([
'css-loader?minimize',
]),
},
...cssPlugins.map(extract), {
test: /\.(png|gif|svg|woff|woff2|eot|ttf)$/,
loader: 'url-loader?limit=50000',
}];
module.exports = {
plugins,
module: {
rules,
},
};
function getCSSList(dir) {
const base = (a) => basename(a, extname(a));
const addDir = (name) => `${dir}/${name}`;
const rootDir = join(__dirname, '..');
return fs.readdirSync(`${rootDir}/css/${dir}`)
.map(base)
.map(addDir);
}
function extract(extractPlugin) {
const {filename} = extractPlugin;
const loader = isDev ? 'css-loader' : 'css-loader?minimize';
return {
test: RegExp(`css/${filename}`),
use: extractPlugin.extract([
loader
])
};
}

43
.webpack/html.js Normal file
View file

@ -0,0 +1,43 @@
'use strict';
const {env} = process;
const isDev = env.NODE_ENV === 'development';
const HtmlWebpackPlugin = require('html-webpack-plugin');
const plugins = [
new HtmlWebpackPlugin({
inject: false,
template: 'html/index.html',
minify: !isDev && getMinifyHtmlOptions(),
}),
];
module.exports = {
plugins,
};
function getMinifyHtmlOptions() {
return {
removeComments: true,
removeCommentsFromCDATA: true,
removeCDATASectionsFromCDATA: true,
collapseWhitespace: true,
collapseBooleanAttributes: true,
removeAttributeQuotes: true,
removeRedundantAttributes: true,
useShortDoctype: true,
removeEmptyAttributes: true,
/* оставляем, поскольку у нас
* в элемент fm генерируеться
* таблица файлов
*/
removeEmptyElements: false,
removeOptionalTags: true,
removeScriptTypeAttributes: true,
removeStyleLinkTypeAttributes: true,
minifyJS: true,
};
}

92
.webpack/js.js Normal file
View file

@ -0,0 +1,92 @@
'use strict';
const {
resolve,
sep,
join,
} = require('path');
const dir = './client';
const dirModules = './client/modules';
const modules = './modules';
const {env} = process;
const isDev = env.NODE_ENV === 'development';
const rootDir = join(__dirname, '..');
const dist = resolve(rootDir, 'dist');
const distDev = resolve(rootDir, 'dist-dev');
const devtool = isDev ? 'eval' : 'source-map';
const notEmpty = (a) => a;
const clean = (array) => array.filter(notEmpty);
const rules = clean([
!isDev && {
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
}]);
const splitChunks = {
chunks: 'all',
name: 'cloudcmd.common',
};
module.exports = {
devtool,
optimization: {
splitChunks,
},
entry: {
cloudcmd: `${dir}/cloudcmd.js`,
[modules + '/edit']: `${dirModules}/edit.js`,
[modules + '/edit-file']: `${dirModules}/edit-file.js`,
[modules + '/edit-file-vim']: `${dirModules}/edit-file-vim.js`,
[modules + '/edit-names']: `${dirModules}/edit-names.js`,
[modules + '/menu']: `${dirModules}/menu.js`,
[modules + '/view']: `${dirModules}/view.js`,
[modules + '/help']: `${dirModules}/help.js`,
[modules + '/markdown']: `${dirModules}/markdown.js`,
[modules + '/config']: `${dirModules}/config.js`,
[modules + '/contact']: `${dirModules}/contact.js`,
[modules + '/upload']: `${dirModules}/upload.js`,
[modules + '/operation']: `${dirModules}/operation/index.js`,
[modules + '/konsole']: `${dirModules}/konsole.js`,
[modules + '/terminal']: `${dirModules}/terminal.js`,
[modules + '/cloud']: `${dirModules}/cloud.js`,
[modules + '/polyfill']: `${dirModules}/polyfill.js`,
},
output: {
filename: '[name].js',
path: isDev ? distDev : dist,
pathinfo: isDev,
devtoolModuleFilenameTemplate,
},
externals: [
externals
],
module: {
rules,
},
};
function externals(context, request, fn) {
if (!isDev)
return fn();
const list = [
'es6-promise',
];
if (list.includes(request))
return fn(null, request);
fn();
}
function devtoolModuleFilenameTemplate(info) {
const resource = info.absoluteResourcePath.replace(__dirname + sep, '');
return `file://cloudcmd/${resource}`;
}

View file

@ -40,7 +40,7 @@
},
"config": {
"dirs": "bin/cloudcmd.js common server",
"dirs_test": "test bin/release.js webpack.config.js"
"dirs_test": "test bin/release.js webpack.config.js .webpack"
},
"scripts": {
"start": "node bin/cloudcmd.js",

View file

@ -1,176 +1,18 @@
'use strict';
const fs = require('fs');
const {
resolve,
basename,
extname,
sep,
} = require('path');
const deepmerge = require('deepmerge');
const dir = './client';
const dirModules = './client/modules';
const modules = './modules';
const isSimpleObject = ({constructor}) => constructor === Object;
const {isArray} = Array;
const isMergeableObject = (a) => isArray(a) || isSimpleObject(a);
const {env} = process;
const isDev = env.NODE_ENV === 'development';
const htmlConfig = require('./.webpack/html');
const cssConfig = require('./.webpack/css');
const jsConfig = require('./.webpack/js');
const dist = resolve(__dirname, 'dist');
const distDev = resolve(__dirname, 'dist-dev');
const devtool = isDev ? 'eval' : 'source-map';
const notEmpty = (a) => a;
const clean = (array) => array.filter(notEmpty);
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const extractCSS = (a) => new ExtractTextPlugin(`${a}.css`);
const extractMain = extractCSS('[name]');
const cssNames = [
'nojs',
'view',
'config',
...getCSSList('columns'),
];
const cssPlugins = cssNames.map(extractCSS);
const plugins = [
new HtmlWebpackPlugin({
inject: false,
template: 'html/index.html',
minify: !isDev && getMinifyHtmlOptions(),
}),
...cssPlugins,
extractMain,
];
const rules = clean([
!isDev && {
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
}, {
test: /\.css$/,
exclude: /css\/(nojs|view|config|columns.*)\.css/,
use: extractMain.extract([
'css-loader?minimize',
]),
},
...cssPlugins.map(extract),
{
test: /\.(png|gif|svg|woff|woff2|eot|ttf)$/,
loader: 'url-loader?limit=50000',
},
]);
const splitChunks = {
chunks: 'all',
name: 'cloudcmd.common',
};
module.exports = {
devtool,
optimization: {
splitChunks,
},
entry: {
cloudcmd: `${dir}/cloudcmd.js`,
[modules + '/edit']: `${dirModules}/edit.js`,
[modules + '/edit-file']: `${dirModules}/edit-file.js`,
[modules + '/edit-file-vim']: `${dirModules}/edit-file-vim.js`,
[modules + '/edit-names']: `${dirModules}/edit-names.js`,
[modules + '/menu']: `${dirModules}/menu.js`,
[modules + '/view']: `${dirModules}/view.js`,
[modules + '/help']: `${dirModules}/help.js`,
[modules + '/markdown']: `${dirModules}/markdown.js`,
[modules + '/config']: `${dirModules}/config.js`,
[modules + '/contact']: `${dirModules}/contact.js`,
[modules + '/upload']: `${dirModules}/upload.js`,
[modules + '/operation']: `${dirModules}/operation/index.js`,
[modules + '/konsole']: `${dirModules}/konsole.js`,
[modules + '/terminal']: `${dirModules}/terminal.js`,
[modules + '/cloud']: `${dirModules}/cloud.js`,
[modules + '/polyfill']: `${dirModules}/polyfill.js`,
},
output: {
filename: '[name].js',
path: isDev ? distDev : dist,
pathinfo: isDev,
devtoolModuleFilenameTemplate,
},
plugins,
externals: [
externals
],
module: {
rules,
},
};
function getCSSList(dir) {
const base = (a) => basename(a, extname(a));
const addDir = (name) => `${dir}/${name}`;
return fs.readdirSync(`./css/${dir}`)
.map(base)
.map(addDir);
}
function externals(context, request, fn) {
if (!isDev)
return fn();
const list = [
'es6-promise',
];
if (list.includes(request))
return fn(null, request);
fn();
}
function devtoolModuleFilenameTemplate(info) {
const resource = info.absoluteResourcePath.replace(__dirname + sep, '');
return `file://cloudcmd/${resource}`;
}
function extract(extractPlugin) {
const {filename} = extractPlugin;
const loader = isDev ? 'css-loader' : 'css-loader?minimize';
return {
test: RegExp(`css/${filename}`),
use: extractPlugin.extract([
loader
])
};
}
function getMinifyHtmlOptions() {
return {
removeComments: true,
removeCommentsFromCDATA: true,
removeCDATASectionsFromCDATA: true,
collapseWhitespace: true,
collapseBooleanAttributes: true,
removeAttributeQuotes: true,
removeRedundantAttributes: true,
useShortDoctype: true,
removeEmptyAttributes: true,
/* оставляем, поскольку у нас
* в элемент fm генерируеться
* таблица файлов
*/
removeEmptyElements: false,
removeOptionalTags: true,
removeScriptTypeAttributes: true,
removeStyleLinkTypeAttributes: true,
minifyJS: true,
};
}
module.exports = deepmerge.all([
jsConfig,
htmlConfig,
cssConfig,
], {isMergeableObject});