使用webpack观看时,当我更改JS或CSS文件时,会生成该包,但在浏览器中,我收到了coffee,vue或jsx文件的错误:
You may need an appropriate loader to handle this file type.
如果在一个项目中使用coffee,vue,jsx和js,是否有特殊方法可以使用webpack进行观察?
webpack.config.js
const shouldMinify = process.env.NODE_ENV === 'production';
const shouldAnalize = false;
const path = require('path');
const R = require('ramda');
const webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const SpritesmithPlugin = require('webpack-spritesmith');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const dateTime = new Date().getTime();
const distDir = '../../../dist/user-panel';
const tempDir = '.tmp';
// TODO: imagemin loader
const rules = {
fonts: {
test: /\.(ttf|otf|eot|svg|woff(2)?)(\?[a-z0-9]+)?$/,
loader: 'file-loader?name=font/icons/[name].[ext]'
},
css: {
test: /\.css$/,
loader: ExtractTextPlugin.extract({fallback: 'style-loader', use: 'css-loader!postcss-loader'})
},
scss: {
test: /\.scss$/,
loader: ExtractTextPlugin.extract({fallback: 'style-loader', use: 'css-loader!postcss-loader!sass-loader'}),
},
images: {
test: /\.(jpg|svg|gif|png(2)?)(\?[a-z0-9]+)?$/,
loader: 'file-loader'
},
js: {
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
},
vue: {
test: /\.vue$/,
loader: 'vue-loader',
options: {
loaders: {
js: 'babel-loader!eslint-loader'
}
}
},
coffee: {
test: /\.coffee$/,
use: ['coffee-loader']
},
html: {
test: /\.html$/,
loader: 'ng-cache-loader?prefix=[dir]/[dir]',
exclude: path.resolve(__dirname, 'src/index.html')
},
// TODO: import zeroclipboard to clipboard module ?
swf: {
test: /\.swf$/,
loader: 'file-loader'
},
};
const vendors = [
'jquery',
'bootstrap-datepicker/dist/js/bootstrap-datepicker',
'bootstrap-datepicker/dist/css/bootstrap-datepicker.standalone.css',
'select2/dist/js/select2.full.js',
'select2/src/scss/core.scss',
'ramda',
'moment/moment.js',
'lodash',
'angular',
'angular-route',
'bignumber.js',
'node-uuid',
'socket.io-client/dist/socket.io',
'jquery-flot/jquery.flot.js',
'jquery-flot/jquery.flot.time.js',
'zeroclipboard',
'js-cookie',
'animate.css/animate.css',
'qrcodejs/qrcode.js',
];
const filesToCopy = [{
from: '{common,components,modules}/**/*.html',
context: 'src/'
}, {
from: 'templates/**/*.html',
context: 'src/'
}, {
from: 'images/*.{jpg,gif,png}',
context: 'src/common/assets/',
}, {
from: 'images/currencies-flags-round/*.{jpg,gif,png}',
context: 'src/common/assets/',
}, {
from: 'images/*',
context: tempDir + '/'
}];
const plugins = [
new webpack.ProvidePlugin({
"window.jQuery": "jquery",
"jQuery": "jquery",
$: 'jquery',
}),
new ExtractTextPlugin({filename: '[name].[chunkhash].css', allChunks: true}),
new webpack.optimize.CommonsChunkPlugin({name: 'vendor', filename: 'vendor.[chunkhash].js', minChunks: Infinity}),
new webpack.ContextReplacementPlugin(/moment[\/\\]locale$/, /pl|en/),
new CopyWebpackPlugin(filesToCopy),
new HtmlWebpackPlugin({
template: './src/index.html',
minify: shouldMinify ? {
collapseWhitespace: true,
conservativeCollapse: false
} : {}
}),
new SpritesmithPlugin({
src: {
cwd: 'src/common/assets/images/sass-images/',
glob: '**/*.{png,jpg}'
},
target: {
image: distDir + '/images/sass-images-' + dateTime + '.png',
css: '.tmp/style/sass-images.scss'
},
spritesmithOptions: {
algorithm: 'top-down'
},
apiOptions: {
cssImageRef: '/dist/user-panel/images/sass-images-' + dateTime + '.png'
}
}),
new SpritesmithPlugin({
src: {
cwd: 'src/common/assets/images/currencies-flags/',
glob: '*.png'
},
target: {
image: distDir + '/images/currencies-flags-' + dateTime + '.png',
css: [['.tmp/style/currencies-flags.css', {
format: 'currencies_flags_template'
}]]
},
spritesmithOptions: {
algorithm: 'top-down'
},
apiOptions: {
cssImageRef: '/dist/user-panel/images/currencies-flags-' + dateTime + '.png'
},
customTemplates: {
'currencies_flags_template': (data) => {
return data.sprites.map((sprite) => {
return 'span.replN:before { width: replWpx; height: replHpx; background-position: replXpx replYpx; background-image: url(replI); }'
.replace('replN', sprite.name.toUpperCase())
.replace('replW', sprite.width)
.replace('replH', sprite.height)
.replace('replX', sprite.offset_x)
.replace('replY', sprite.offset_y)
.replace('replI', sprite.image);
}).join('\n');
}
}
}),
new SpritesmithPlugin({
src: {
cwd: 'src/common/assets/images/countries-flags/',
glob: '*.png'
},
target: {
image: distDir + '/images/countries-flags-' + dateTime + '.png',
css: [['.tmp/style/countries-flags.css', {
format: 'countries_flags_template'
}]]
},
spritesmithOptions: {
algorithm: 'top-down'
},
apiOptions: {
cssImageRef: '/dist/user-panel/images/countries-flags-' + dateTime + '.png'
},
customTemplates: {
'countries_flags_template': (data) => {
return data.sprites.map((sprite) => {
return 'span.replN:before { width: replWpx; height: replHpx; background-position: replXpx replYpx; background-image: url(replI); }'
.replace('replN', sprite.name)
.replace('replW', sprite.width)
.replace('replH', sprite.height)
.replace('replX', sprite.offset_x)
.replace('replY', sprite.offset_y)
.replace('replI', sprite.image);
}).join('\n');
}
}
}),
new SpritesmithPlugin({
src: {
cwd: 'src/common/assets/images/banks/',
glob: '*.png'
},
target: {
image: distDir + '/images/banks-' + dateTime + '.png',
css: [['.tmp/style/banks.css', {
format: 'banks_template'
}]]
},
spritesmithOptions: {
algorithm: 'top-down'
},
apiOptions: {
cssImageRef: '/dist/user-panel/images/banks-' + dateTime + '.png'
},
customTemplates: {
'banks_template': (data) => {
return data.sprites.map((sprite) => {
return '.bank_replN { width: replWpx; height: replHpx; background-position: replXpx replYpx; background-image: url(replI); }'
.replace('replN', sprite.name)
.replace('replW', sprite.width)
.replace('replH', sprite.height)
.replace('replX', sprite.offset_x)
.replace('replY', sprite.offset_y)
.replace('replI', sprite.image);
}).join('\n');
}
}
}),
];
const analyzePlugins = shouldAnalize
? [
new BundleAnalyzerPlugin(),
]
: [];
const devtool = shouldMinify ? 'cheap-source-map' : 'eval';
module.exports = {
entry: {
app: [
'babel-polyfill',
'./src/common/scripts/app.js',
],
vendor: vendors
},
output: {
filename: "[name].[chunkhash].js",
path: path.join(__dirname, distDir),
publicPath: '/dist/user-panel/'
},
devtool: devtool,
module: {
loaders: [
rules.js,
rules.coffee,
rules.vue,
rules.fonts,
rules.css,
rules.scss,
rules.images,
rules.html
],
},
resolve: {
extensions: ['.js', '.json', '.coffee', '.vue'],
alias: {
'jquery': require.resolve('jquery'),
}
},
plugins: R.concat(analyzePlugins, plugins),
watchOptions: {
aggregateTimeout: 300,
poll: 1000
},
// stats: 'errors-only'
stats: 'minimal'
};