Nek
Nek

Reputation: 3115

How to configure global css and sass stylesheet with webpack, typescript, phaser and angular

The following configuration is made by hand to support all technologies given in the title (webpack, typescript, phaser and angular).

It works great for angular component stylesheet. But it looks like it's impossible to include a global style sheet. Here are related configuration files:

HTML file:

<!-- src/index.html -->
<!DOCTYPE html>
<html>
  <head>
    <base href="/">
    <meta charset="UTF-8">
    <!-- it's included here! -->
    <link rel="stylesheet" href="styles/main.css">
    <meta name="viewport" content="width=device-width, initial-scale=1">
  </head>
  <body>
    <app-root></app-root>
  </body>
</html>

CSS file:

/*
src/styles/main.css
This file is correctly loaded in dev environment. When I build the project it disapear. :(
*/
body {
    background: #253050 url('../assets/design/main_background.jpg') no-repeat center;
}

And webpack configuration:

// config/webpack.common.js
'use strict';

var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
const path = require('path');
var helpers = require('./helpers');

var distDir = path.resolve(__dirname, '../dist');

// Phaser webpack config
const phaserModule = path.join(__dirname, '/../node_modules/phaser-ce/');
const phaser = path.join(phaserModule, 'build/custom/phaser-split.js');
const pixi = path.join(phaserModule, 'build/custom/pixi.js');
const p2 = path.join(phaserModule, 'build/custom/p2.js');

module.exports = {
    entry: {
        'polyfills': './src/polyfills.ts',
        "app": "./src/main.ts"
    },

    // What files webpack will manage
    resolve: {
        extensions: ['.js', '.ts', '.tsx'],
        alias: {
            'phaser': phaser,
            'pixi': pixi,
            'p2': p2
        }
    },
    output: {
        path: distDir,
        filename: '[name]_bundle.js'
    },

    module: {
        rules: [
            { test: /assets(\/|\\)/, use: [ 'file-loader' ] },
            {
                test: /\.tsx?$/,
                // ts-loader loads typescript files
                // angular2-template-loader is needed to load component templates
                loaders: ['ts-loader', 'angular2-template-loader'],
                exclude: [
                    /.+phaser-ce\/typescript\/.+\.ts$/,
                    /typescript\/.+\.d\.ts$/
                ]
            },
            {
              test: /\.html$/,
              loader: 'html-loader'
            },

            // to-string-loader is for css loaded by angular components
            // .... and loading angular css work as expected.
            { test: /\.css$/, loaders: ['to-string-loader', 'css-loader'] },
            {
              test: /\.scss$/, // I'd like so much sass work but guess what... it doesn't!
              use: ['to-string-loader', 'css-loader', 'sass-loader']
            },

            // Because phaser and its dependencies are not made for TypeScript and webpack
            { test: /pixi\.js/, use: [{loader: 'expose-loader', options: 'PIXI'}] },
            { test: /phaser-split\.js$/, use: [{loader: 'expose-loader', options: 'Phaser'}] },
            { test: /p2\.js/, use: [{loader: 'expose-loader', options: 'p2'}] }
        ]
    },

    plugins: [
        new webpack.ContextReplacementPlugin(
            // The (\\|\/) piece accounts for path separators in *nix and Windows

            // For Angular 5, see also https://github.com/angular/angular/issues/20357#issuecomment-343683491
            /\@angular(\\|\/)core(\\|\/)esm5/,
            helpers.root('src'), // location of your src
            {
              // your Angular Async Route paths relative to this root directory
            }
          ),
        new CleanWebpackPlugin([distDir]),
        new HtmlWebpackPlugin({
            template: 'src/index.html',
            chunksSortMode: function(a, b) {
                // set the load order !
                var order = ["polyfills", "app"];
                return order.indexOf(a.names[0]) - order.indexOf(b.names[0]);
            }
        })
    ]
};

And here is webpack.prod.js configuration:

module.exports = merge(common, {
    devtool: 'source-map',
    plugins: [
        // stops the build if there is an error
        new webpack.NoEmitOnErrorsPlugin(),
        new UglifyJSPlugin({sourceMap: true}),
        // extracts embedded css as external files, adding cache-busting hash to the filename
        new ExtractTextPlugin('[name].[hash].css'),
        new webpack.DefinePlugin({
            'process.env.NODE_ENV': JSON.stringify('production')
        })
    ]
});

When I run webpack --config config/webpack.prod.js the global CSS is not load, there is no error. Just no CSS.

Feel free to explain also how to load SCSS because it doesn't work even in development mode for me.

Thanks!

Upvotes: 3

Views: 6606

Answers (3)

Nek
Nek

Reputation: 3115

I finally make it work. So here is the changes I made:

1) The path to style.css is now ignored in css/scss clauses.

{
  exclude: path.resolve(__dirname, '../src/styles'),
  test: /\.css$/, loaders: ['to-string-loader', 'css-loader']
},
{
  exclude: path.resolve(__dirname, '../src/styles'),
  test: /\.scss$/,
  use: ['to-string-loader', 'css-loader', 'sass-loader']
}

2) The I added a new entry file for the CSS

entry: {
  'polyfills': './src/polyfills.ts',
  'app': './src/main.ts',
  'css': './src/styles/main.css'
}

3) It works because I also configured a new rule that uses the ExtractTextPlugin

{
  test: /\.css$/,
  exclude: path.resolve(__dirname, '../src/app'),
  use: ExtractTextPlugin.extract({
    fallback: 'style-loader',
    use: 'css-loader'
  })
}

Notice that this works also because the prod configuration specify new ExtractTextPlugin('[name].[hash].css') as plugin. (it means you need to add it in the common configuration to avoid any error in dev environment)

Upvotes: 5

Nothing Mi
Nothing Mi

Reputation: 332

more global styles can be set in .angular-cli.json, it maybe looks like this:

...
"apps": [
    {
      ...

      "styles": [
          "app/core/preloader/preloader.scss",
          "styles.scss"
      ],
      ...
    }
]
...

in app section, you should found that more global assets/scripts can be set here.

more about .angluar-cli.json is here

Upvotes: -2

SantoshK
SantoshK

Reputation: 1877

I Think you need to use angular-cli where you can set the custom css url in angular-cli.JSON like as below :

"styles": [
        "../node_modules/bootstrap/dist/css/bootstrap.min.css",
        "../node_modules/font-awesome/css/font-awesome.min.css"

      ],

Upvotes: -2

Related Questions