Я использую babel v6.x и webpack v2.x для переноса кода ES6, а также для сборки и объединения всего кода приложения (конфиги ниже).
Приложение предназначено в первую очередь для IE11 и будет работать во внутренней сети клиента.
Я также использую некоторые заливки ES6 для IE11.
Проблема в том, что код, созданный даже для производственной среды, по-прежнему помещается в оболочку webpackJsonp
и организуется в виде модулей.
То, чего я хотел бы добиться, - это пакет приложения .js и пакет кода стороннего поставщика, который полностью переносится в ES5 IIFE, минимизируется и расширяется, без каких-либо оболочек или секций на модули.
Лучше всего, если бы я мог получить этот результат также для кода, обслуживаемого webpack-dev-server, а не только для окончательной сборки dist приложения.
Таким образом, в основном, код результата должен быть ES5 IIFE, сохраненным в *.min.js
файлах.
Зачем? Потому что я собираюсь использовать webpack только во время сборки и комплектации, а не все время и только тогда.
Я хотел бы отметить, что текущие документы веб-пакетов переписаны для использования в основном с веб-пакетом v4, поэтому не все понятно для моего v2.
Как мне этого добиться?
webpack.config.js
:
var path = require('path');
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var execSync = require('child_process').execSync;
module.exports = function (env) {
var appSettings = require(path.join(__dirname, 'client/settings.js'));
var indexFile = 'client/index.html';
var revisionHash = execSync('git rev-parse HEAD').toString().trim().substring(0, 6);
var revisionCount = execSync('git rev-list --count HEAD').toString().trim();
var buildDate = new Date().toISOString();
var revision = revisionHash + ' (' + revisionCount + ') built on ' + buildDate;
return {
entry: {},
target: "node",
module: {
rules: [
{
test: /\.js$/,
include: [/client/, path.resolve(__dirname, 'node_modules/core-web')],
use: [
'ng-annotate-loader',
{
loader: 'babel-loader',
options: {
presets: [['env', {
"targets": {
"ie": "11"
}
}]]
}
}
]
},
{
test: /\.(png|jpg|jpeg|gif|html|json|pdf|csv)$/,
loader: 'file-loader',
options: {
publicPath: '/'
}
},
{
test: /\.(jar|xml|dll)$/,
loader: 'file-loader',
options: {
publicPath: '/',
name: '[name].[ext]'
}
},
{
test: /\.(eot|svg|ttf|woff(2)?)(\?v=\d+\.\d+\.\d+)?/,
loader: 'file-loader',
options: {
publicPath: '/'
}
},
{
test: /\.less$/,
loader: ExtractTextPlugin.extract({
fallbackLoader: 'style-loader',
loader: ['css-loader', 'postcss-loader', 'less-loader'],
publicPath: path.resolve(__dirname, 'dist')
})
},
{
test: /\.css$/,
loader: ExtractTextPlugin.extract({
fallbackLoader: 'style-loader',
loader: ['css-loader', 'postcss-loader'],
publicPath: path.resolve(__dirname, 'dist')
})
}
]
},
resolve: {
modules: [
'node_modules',
path.resolve(__dirname)
],
alias: {
common: 'client/app/common',
img: 'client/app/common/static/img'
}
},
plugins: [
new ExtractTextPlugin('[name].[hash].css'),
// Injects bundles in your index.html instead of wiring all manually.
// It also adds hash to all injected assets so we don't have problems
// with cache purging during deployment.
new HtmlWebpackPlugin({
template: indexFile,
favicon: 'client/app/common/static/favicon.ico',
inject: 'body',
hash: true
}),
new webpack.DefinePlugin({
__API_URL__: JSON.stringify(appSettings[env] || ''),
__REVISION__: JSON.stringify(revision)
}),
// Automatically move all modules defined outside of application directory to vendor bundle.
// If you are using more complicated project structure, consider to specify common chunks manually.
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: function (module, count) {
return module.resource && module.resource.indexOf(path.resolve(__dirname, 'client')) === -1;
}
}),
new webpack.optimize.UglifyJsPlugin({})
]
}
};
webpack.dev.config.js
var webpack = require('webpack');
var path = require('path');
var config = require('./webpack.config')('DEV');
config.output = {
filename: '[name].bundle.js',
publicPath: '/',
path: path.resolve(__dirname, 'client')
};
config.plugins = config.plugins.concat([
// Adds webpack HMR support. It act's like livereload,
// reloading page after webpack rebuilt modules.
// It also updates stylesheets and inline assets without page reloading.
new webpack.HotModuleReplacementPlugin()
]);
module.exports = config;
webpack.dist.config.js
const webpack = require('webpack');
const path = require('path');
const config = require('./webpack.config')('PROD');
const yargs = require('yargs');
config.output = {
filename: '[name].[hash].js',
publicPath: '',
path: path.resolve(__dirname, 'dist')
};
const plugins = [];
if(!yargs.argv.dev) {
plugins.push(
// Reduces bundles total size
new webpack.optimize.UglifyJsPlugin({
mangle: {
// You can specify all variables that should not be mangled.
// For example if your vendor dependency doesn't use modules
// and relies on global variables. Most of angular modules relies on
// angular global variable, so we should keep it unchanged
except: ['$super', '$', 'exports', 'require', 'angular']
}
})
);
}
config.plugins = config.plugins.concat(plugins);
module.exports = config;
gulpfile.babel.js
const gulp = require('gulp');
const webpack = require('webpack');
const path = require('path');
const rename = require('gulp-rename');
const template = require('gulp-template');
const yargs = require('yargs');
const gutil = require('gulp-util');
const serve = require('browser-sync');
const del = require('del');
const webpackDevMiddelware = require('webpack-dev-middleware');
const webpachHotMiddelware = require('webpack-hot-middleware');
const colorsSupported = require('supports-color');
const historyApiFallback = require('connect-history-api-fallback');
const generator = require('core-web/generator');
const camelCase = require('lodash/camelCase');
const zip = require('gulp-zip');
const moment = require('moment');
const root = 'client';
// helper method for resolving paths
const resolveToApp = (glob = '') => path.join(root, 'app', glob);
const resolveToComponents = (glob = '') => path.join(root, 'app/components', glob);
// map of all paths
const paths = {
js: resolveToComponents('**/*!(.spec.js).js'), // exclude spec files
less: resolveToApp('**/*.less'), // stylesheets
html: [
resolveToApp('**/*.html'),
path.join(root, 'index.html')
],
entry: {
dev: path.join(__dirname, root, 'environments/dev.js'),
uat: path.join(__dirname, root, 'environments/uat.js'),
prod: path.join(__dirname, root, 'environments/prod.js')
},
polyfill: path.join(__dirname, root, 'app/common/vendors/polyfill/polyfill.js'),
output: root,
blankTemplates: path.join(__dirname, path.relative(__dirname, generator), 'component/**/*.**'),
dest: path.join(__dirname, 'dist')
};
const zipDist = () => {
const now = moment().format('YYYYMMDDHHmm');
const zipName = 'app_' + now + '.zip';
gulp
.src('dist/**/*', { dot: true })
.pipe(zip(zipName))
.pipe(gulp.dest(paths.dest));
};
// use webpack.config.js to build modules
gulp.task('webpack', ['clean'], cb => {
const config = require('./webpack.dist.config');
config.entry.app = yargs.argv.uat ? paths.entry.uat : paths.entry.prod;
config.entry.polyfill = paths.polyfill;
if (yargs.argv.uat) {
config.devtool = 'eval-source-map';
}
webpack(config, (err, stats) => {
if (err) {
throw new gutil.PluginError('webpack', err);
}
gutil.log('[webpack]', stats.toString({
colors: colorsSupported,
chunks: false,
errorDetails: true
}));
gulp
.src('./.htaccess')
.pipe(gulp.dest(paths.dest))
.on('data', () => {
zipDist();
});
cb();
});
});
gulp.task('serve', () => {
const config = require('./webpack.dev.config');
config.entry.app = [
// this modules required to make HRM working
// it responsible for all this webpack magic
'webpack-hot-middleware/client?reload=true',
// application entry point
paths.entry.dev,
paths.polyfill
];
config.devtool = 'eval-source-map';
const compiler = webpack(config);
serve({
port: process.env.PORT || 3000,
open: false,
server: { baseDir: root },
middleware: [
historyApiFallback(),
webpackDevMiddelware(compiler, {
stats: {
colors: colorsSupported,
chunks: false,
modules: false
},
publicPath: config.output.publicPath
}),
webpachHotMiddelware(compiler)
]
});
});
gulp.task('watch', ['serve']);
gulp.task('component', () => {
const cap = val => {
return val.charAt(0).toUpperCase() + val.slice(1);
};
const name = yargs.argv.name;
const parentPath = yargs.argv.parent || '';
const destPath = path.join(resolveToComponents(), parentPath, name);
return gulp.src(paths.blankTemplates)
.pipe(template({
name,
upCaseName: cap(name),
parent: parentPath,
fullName: camelCase(parentPath + ' ' + name)
}))
.pipe(rename(dir => {
dir.basename = dir.basename.replace('temp', name);
}))
.pipe(gulp.dest(destPath));
});
gulp.task('clean', cb => {
del([paths.dest]).then(dir => {
gutil.log('[clean]', dir);
cb();
});
});
gulp.task('default', ['watch']);
.babelrc
{
"presets": [['env', {
"targets": {
"ie": "11"
}
}]]
}