Setting up a global CSS and SASS stylesheet for webpack, TypeScript, Phaser, and Angular: A step-by-step guide

A manual configuration has been set up to accommodate all the technologies mentioned in the title (webpack, typescript, phaser, and angular).

While it works perfectly for angular component stylesheets, there seems to be an issue with including a global stylesheet. Below are the relevant configuration files:

HTML file:

<!-- src/index.html -->
<!DOCTYPE html>
<html>
  <head>
    <base href="/">
    <meta charset="UTF-8">
    <!-- 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 the dev environment but disappears when I build the project. :(
*/
body {
    background: #253050 url('../assets/design/main_background.jpg') no-repeat center;
}

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?$/,
                loaders: ['ts-loader', 'angular2-template-loader'],
                exclude: [
                    /.+phaser-ce\/typescript\/.+\.ts$/,
                    /typescript\/.+\.d\.ts$/
                ]
            },
            {
              test: /\.html$/,
              loader: 'html-loader'
            },
            
            { test: /\.css$/, loaders: ['to-string-loader', 'css-loader'] },
            {
              test: /\.scss$/, 
              use: ['to-string-loader', 'css-loader', 'sass-loader']
            },
            
            { 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(
            /\@angular(\\|\/)core(\\|\/)esm5/,
            helpers.root('src')
          ),
        new CleanWebpackPlugin([distDir]),
        new HtmlWebpackPlugin({
            template: 'src/index.html',
            chunksSortMode: function(a, b) {
                var order = ["polyfills", "app"];
                return order.indexOf(a.names[0]) - order.indexOf(b.names[0]);
            }
        })
    ]
};

And here is the webpack.prod.js configuration:

module.exports = merge(common, {
    devtool: 'source-map',
    plugins: [
        new webpack.NoEmitOnErrorsPlugin(),
        new UglifyJSPlugin({sourceMap: true}),
        new ExtractTextPlugin('[name].[hash].css'),
        new webpack.DefinePlugin({
            'process.env.NODE_ENV': JSON.stringify('production')
        })
    ]
});

When running

webpack --config config/webpack.prod.js
, the global CSS fails to load without any errors being displayed.

If anyone could provide insights on how to successfully load SCSS, especially during development mode, it would be greatly appreciated!

Answer №1

After some tinkering, I finally got it to work. Here are the changes I made:

1) I stopped including the path to style.css 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) I introduced a new entry file for the CSS

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

3) It started working because I set up a new rule that utilizes the ExtractTextPlugin

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

Note that this solution also relies on the prod configuration specifying

new ExtractTextPlugin('[name].[hash].css')
as a plugin. (Make sure to include it in the common configuration to prevent errors in the dev environment)

Answer №2

To achieve this, consider utilizing the angular-cli tool and specifying the custom css url in the angular-cli.JSON file as shown below:

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

Answer №3

To customize global styles, you can adjust settings in the .angular-cli.json file. An example configuration may appear like this:

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

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

Within the app section of the file, you will discover options to set additional global assets and scripts.

For more information on .angular-cli.json, please refer to the documentation here

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the method for including as: :json in your code?

I have a file with the extension .ts, which is part of a Ruby on Rails application. The code in this file looks something like this: export const create = async (params: CreateRequest): Promise<XYZ> => { const response = await request<XYZ> ...

Is there a way to prevent the window.status from appearing?

I currently have the following code snippet: <a class="button accessLink" id="loginLink" href="#" data-action="Login" data-dialog="access" data-disabled="false" data-entity="n/a" ...

Tips for finding the displayRows paragraph within the MUI table pagination, nestled between the preceding and succeeding page buttons

Incorporating a Material-UI table pagination component into my React application, I am striving to position the text that indicates the current range of rows between the two action buttons (previous and next). <TablePagination ...

Tips for formatting the return Date when utilizing the setDate() method

I set the end of the week to be the upcoming weekend using the following code snippet this.weekEnd = new Date(this.currentDate.setDate(end)); Now, my goal is to update the weekEnd by adding 7 days to it. I attempted to achieve this as shown below, however ...

What are some ways to prevent popups from being hidden by CSS?

I encountered a problem with my popup that I created using pure CSS. When I move my mouse to the top or bottom of the window, the popup disappears. However, if my cursor is in the body area, the popup appears as intended. I have not used any JavaScript in ...

Exploring Angular 2: The Power of HTTP Observables for Managing Asynchronous Operations. Exploring the

When working with a form that fetches data using an http observable, I encountered the need to disable the submit button while awaiting the response. Currently, I am setting the status code on each component/form to indicate running before calling the sub ...

The structure becomes disrupted when the Material Ui grid is enclosed within a div container

I currently have a responsive dashboard built with Material Ui's Grid elements. One of the grid items is wrapped in a div element, causing the layout to break. Check out the playground with the div element here: https://codesandbox.io/s/basicgrid-mat ...

Cypress Issue: Exceeded 5000ms Waiting for `cy.wait()`...No Network Request Detected

I recently decided to dive into building a React app using Vite, Chakra-UI, and TypeScript, incorporating Cypress for testing. The main objective was to expand my knowledge on these technologies. Interestingly enough, this marks my first experience with Cy ...

Is it necessary to install only form control styles from Bootstrap 4?

Does Bootstrap 4 offer a way to only install the form control styles like input group? I came across a resource that allows you to solely install the Bootstrap 4 Grid. Is there anything similar for downloading just the form styles? ...

A new version of Primefaces has been released, introducing a sleek button feature with

How can I utilize the Primefaces version 10 button with a Font Awesome icon, resizing the icon without displaying the words ui:button? A and B are tests that I can resize successfully, but they are not buttons. C and D are buttons where the icon is resize ...

Sub-objects in Angular 2 with observables

I need guidance on understanding Observables/Subjects in Angular2. My app includes data of the following structure: sections = [ { _id: '999' name: 'section 1' items: [ { name: "i ...

Angular 15 brings an exciting new feature: the Swiper 9 Element

I went through the swiperjs official documentation found at: swiperjs doc To display images, I created a method to configure and initialize the swiper only when necessary. Below is the HTML code snippet: <swiper-container #swiperRef init="false& ...

The slicing of jQuery parent elements

Hey there! I recently created a simulated "Load More" feature for certain elements within divs. However, I've encountered an issue where clicking on the Load More button causes all elements in both my first and second containers to load simultaneously ...

Arranging JSON elements according to a separate array in Angular 2 or Node.js

Looking for a solution with optimal performance, I am seeking to achieve the rearrangement of a list using either Angular2 or NodeJS. My input consists of user fruit preferences' IDs {15, 43, 55, 67, 98}; In addition, I have a JSON object containin ...

Identified the category

How can I retrieve the default option from a list of options? type export type Unpacked<T> = T extends Array<infer U> ? U : T; interface getDefaultValue?: <T extends Option[]>(options: T) => Unpacked<T>; Example const options = ...

Navigate to a different component within Angular

Is there a way in Angular to scroll to a component using a button placed in another component? Below is the code snippet for the first component: <div id='banner' class="col-5 offset-1 d-flex justify-content-center align-items-cen ...

The OnPrepareResponse method in StaticFileOptions does not trigger when serving the index.html file

Currently, I am attempting to disable caching for index.html in my Angular SPA that is connected to a .NET Core 2.2 backend. I am following the instructions provided in this particular answer by implementing an OnPrepareResponse action for my StaticFileOp ...

Can you explain the purpose and functionality of the following code in Typescript: `export type Replace<T, R> = Omit<T, keyof R> & R;`

Despite my efforts, I am still struggling to grasp the concept of the Replace type. I have thoroughly reviewed the typescript documentation and gained some insight into what is happening in that line, but it remains elusive to me. ...

What should I do about typescript and ES6?

An error occurred while running my code: [0] app/components/people/details/PersonDetailComponent.ts(27,35): error TS2339: Property 'person' is missing from type '{}'. Here is the code snippet in question: export class PersonDeta ...

Why does the final value appear when passing an incrementing counter as a prop to multiple React Components created in a loop?

I am currently unraveling the concept of closures in JavaScript. Within this code snippet, I am cycling through the values of the 'items' array using a foreach loop. I have defined a let variable named "count" outside the scope of the loop. Afte ...