angular2 webpack大包大小与sass

时间:2016-08-15 22:02:35

标签: angular typescript sass webpack

我有webpack包大小问题,这是由sass样式引起的......

我有很多angular2组件,我使用materialize-css库设计。我使用@extend而不是将materialize-css类放在我的html中来封装来自html本身的库。

我遇到的问题是使用webpack的包大小非常大,因为每个组件的sass都会导入materialize-css包,并且因为组件的样式是使用raw加载器加载的,所以它会嵌入到bundle js文件中。所以我得到的是每个组件具有相同materialize-css样式的大包。

仅仅是为了比较我编译了我的应用程序和注释掉的所有样式,当包含样式时,包大小为1.08MB,它是5.26MB

有人能指出我正确的解决方案吗?

谢谢!

编辑: 我的webpack定义:

Webpack.common:

import * as webpack from 'webpack';
import {Configuration} from 'webpack';
import * as path from 'path';
import {PathHelper} from '../../common/pathHelper';
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var HtmlWebpackPlugin = require('html-webpack-plugin');

process.env.ENV = process.env.NODE_ENV;

export var webpackCommonConfiguration: Configuration = {
  entry: {
    'polyfills': './src/app/polyfills.ts',
    'app': './src/app/app.ts',
    'signin': './src/app/signinApp.ts',
    'vendor': './src/app/vendor.ts',
    'design': './src/app/design.scss'
  },
  resolve: {
    extensions: ['', '.ts', '.js', 'scss']
  },
  module: {
    loaders: [
      {
        test: /\.ts$/,
        loader: 'ts'
      },
      {
        test: /\.html$/,
        loader: 'html'
      },
      {
        test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/,
        loader: 'file?name=assets/[name].[hash].[ext]'
      },
      {
        test: /\.scss$/,
        exclude: PathHelper.getPathFromRoot('src', 'app', 'modules'),
        loader: ExtractTextPlugin.extract('style', 'css!resolve-url!sass?sourceMap')
      },
      {
        test: /\.scss$/,
        include: PathHelper.getPathFromRoot('src', 'app', 'modules'),
        loader: 'raw!sass'
      },
      {
        test: /\.css$/,
        exclude: PathHelper.getPathFromRoot('src', 'app', 'modules'),
        loader: ExtractTextPlugin.extract('style', 'css!resolve-url!css?sourceMap')
      },
      {
        test: /\.css$/,
        include: PathHelper.getPathFromRoot('src', 'app', 'modules'),
        loader: 'raw!resolve-url'
      }
    ]
  },
  plugins: [
    new webpack.optimize.CommonsChunkPlugin({
      name: 'signinCommon',
      chunks: ['signin', 'vendor'],
      minChunks: Infinity
    }),
    new webpack.optimize.CommonsChunkPlugin({
      name: 'homeCommon',
      chunks: ['app', 'vendor'],
      minChunks: Infinity
    }),
    new webpack.DefinePlugin({
      'process.env': {
        'ENV': JSON.stringify(process.env.NODE_ENV)
      }
    }),
    new webpack.ProvidePlugin({
      // Required for the velocity plugin to be loaded correctly (used in materialize css)
      "window.$": "jquery",
      "window.jQuery": "jquery",
      "root.jQuery": "jquery"
    }),
    new HtmlWebpackPlugin({
      template: PathHelper.getPathFromRoot('src', 'app', 'views', 'signin.html'),
      filename: 'signin.html',
      chunks: ['polyfills', 'signinCommon', 'design', 'vendor', 'signin']
    }),
    new HtmlWebpackPlugin({
      template: PathHelper.getPathFromRoot('src', 'app', 'views', 'home.html'),
      filename: 'home.html',
      chunks: ['polyfills', 'homeCommon', 'design', 'vendor', 'app']
    })
  ]
}

Webpack.prod:

var webpackMerge = require('webpack-merge');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
import * as webpack from 'webpack';
import {Configuration} from 'webpack';
import {webpackCommonConfiguration} from './webpack.common.config'
import {PathHelper} from '../../common/pathHelper';

interface IProductionConfiguration extends Configuration {
  htmlLoader: any;
}

var config: IProductionConfiguration = {

  devtool: 'source-map',

  output: {
    path: PathHelper.getPathFromRoot('dist'),
    publicPath: '/dist/',
    filename: '[name].[hash].js',
    chunkFilename: '[id].[hash].chunk.js'
  },

  htmlLoader: {
    minimize: false // workaround for ng2
  },

  plugins: [
    new webpack.NoErrorsPlugin(),
    new webpack.optimize.DedupePlugin(),
    new webpack.optimize.UglifyJsPlugin(),
    new ExtractTextPlugin('[name].[hash].css')
  ]
}

export var webpackProductionConfig: Configuration =
  webpackMerge(webpackCommonConfiguration, config);

EDIT2: 组件示例:

credits.component.ts:

import {Component} from '@angular/core';

@Component({
  selector: 'credits',
  template: require('./credits.component.html'),
  styles: [require('./credits.component.scss')]
})
export class CreditsComponent {
}

credits.component.html:

<footer class="page-footer credits-footer">
  <div class="footer-copyright">
    <div class="container">
    © 2016 Created by Slava Shpitalny
    </div>
  </div>
</footer>

credits.component.scss:

@import '~materialize-css/sass/materialize.scss';

:host{

  .page-footer.credits-footer{
    @extend .blue;
    margin: 0;
    padding: 0;

  }
}

2 个答案:

答案 0 :(得分:0)

不要捆绑到单个文件。像一个供应商一个分开捆绑,一个用于pollyfills,一个用于app,一个用于css。使用{{1}}插件创建自己的css文件。使用webpack块可以让生活更轻松。对大型应用程序使用代码拆分。

Read more about it

在生产模式下,您可以使用一些插件来缩小捆绑包,删除注释,删除未使用的代码。

答案 1 :(得分:0)

您可以在主应用组件上使用ViewEncapsulation.None,并将Materialise.scss导入到您应用的SCSS文件中。然后它将全局可用,您无需将其导入其他组件。

例如,您的应用组件可能如下所示:

import { ViewEncapsulation } from '@angular/core';
@Component({
    selector: 'app',
    encapsulation: ViewEncapsulation.None,
    styles: [require('./app.scss')],
    template: require('./app.html')
})

...只有您的主应用程序的SCSS文件才会包含导入:

@import '~materialize-css/sass/materialize.scss';

注意:您可以只导入您使用的Materialize组件,而不是导入materialize.css。这样可以提高效率。

如果您想在子组件中使用变量/ mixin,可以单独导入它们(但不要导入整个Materialise scss!)。

例如,子组件可能会导入_variables.scss_mixins.scss,而不仅仅是materialize.scss

例如:

@import '~materialize-css/sass/components/_mixins.scss';
@import '~materialize-css/sass/components/_variables.scss';

不要忘记,vars / mixins不会被导出,只会导出SCSS的CSS结果,所以如果不使用它们就不会添加到文件大小(不同于包含批量的主要Materialize.scss文件)也是CSS课程)