如果修改JS或CSS文件,Webpack watch不使用coffee-loader,vue-loader

时间:2017-07-20 07:44:07

标签: javascript reactjs webpack coffeescript vuejs2

使用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'
};

0 个答案:

没有答案