Webpack, Angular2 rebuild optimization - performance

I'm trying to compile Angular2 with webpack; here is my setup: I have a vendor.ts file where I have:
import 'es6-shim/es6-shim.min';
import 'reflect-metadata/Reflect.js';
import 'zone.js/dist/zone';
import '#angular/platform-browser';
import '#angular/platform-browser-dynamic';
import '#angular/core';
import '#angular/common';
import '#angular/http';
import '#angular/router-deprecated';
My webpack.config.js:
"use strict";
let path = require('path');
let webpack = require("webpack");
let CommonsChunkPlugin = webpack.optimize.CommonsChunkPlugin;
let ProvidePlugin = webpack.ProvidePlugin;
let UglifyJsPlugin = webpack.optimize.UglifyJsPlugin;
module.exports = {
devtool: 'source-map',
debug: true, // set false in production
cache: true,
entry: {
vendor: './app/vendor.ts',
app: './app/main.ts'
},
output: {
filename: './public/assets/js/[name].js'
},
plugins: [
new webpack.optimize.OccurenceOrderPlugin(true),
new webpack.optimize.CommonsChunkPlugin({name: 'vendor', filename: './public/assets/js/vendor.js', minChunks: Infinity}),
new UglifyJsPlugin({
compress: {
warnings: false
}
})
],
module: {
loaders: [
{
test: /\.ts$/,
loader: 'ts-loader',
query: {
'ignoreDiagnostics': [
2403, // 2403 -> Subsequent variable declarations
2300, // 2300 -> Duplicate identifier
2374, // 2374 -> Duplicate number index signature
2375 // 2375 -> Duplicate string index signature
]
},
exclude: [/\.(spec|e2e)\.ts$/, /node_modules\/(?!(ng2-.+))/]
}
]
},
resolve: {
extensions: ["", ".ts", ".js"]
}
};
So, all is fine, webpack is compiling the stuff, but it's too slow. It's taking 15089ms. I'm planning to add this as a gulp task but this won't work, I have to wait like 3-5 seconds for each save. Is it possible to have a setup where if the chunks don't change, to prevent compilation? This would improve the performance a lot. Thank you in advance for any help.

You have to disable webpack.optimize.* plugins, switch devtool to eval and add transpileOnly: true to ts-loader query.

Related

cypress-fail-fast not skipping tests after a failed test

I'm using the cypress-fail-fast plugin > https://github.com/javierbrea/cypress-fail-fast in my Typescript Cypress config, but it doesn't seem to be working.
// cypress.config.ts
import { defineConfig } from 'cypress';
import plugin from './cypress/plugins/index';
export default defineConfig({
projectId: '**',
fixturesFolder: 'cypress/fixtures',
screenshotOnRunFailure: true,
video: true,
videoCompression: 1,
viewportHeight: 1000,
viewportWidth: 1600,
e2e: {
env: {
API_URL: '**',
CYPRESS_PASSWORD: '**',
},
supportFile: 'cypress/support/index.ts',
baseUrl: 'http://localhost:4200',
experimentalInteractiveRunEvents: true,
setupNodeEvents(on, config) {
plugin(on, config);
},
},
});
// supprt/index.ts
import './commands';
import './hooks';
import 'cypress-real-events/support';
import 'cypress-file-upload';
import 'cypress-fail-fast/plugin';
That's how I got it set up, but after a test fails in a spec, it still runs each test.
You're missing adding the plugin to your node events for e2e.
Per the docs:
// cypress.config.js
module.exports = {
e2e: {
setupNodeEvents(on, config) {
require("cypress-fail-fast/plugin")(on, config);
return config;
},
specPattern: "cypress/integration/**/*.js",
},
};
So in your case, that would be:
...
e2e: {
env: {
API_URL: '**',
CYPRESS_PASSWORD: '**',
},
supportFile: 'cypress/support/index.ts',
baseUrl: 'http://localhost:4200',
experimentalInteractiveRunEvents: true,
setupNodeEvents(on, config) {
plugin(on, config);
require("cypress-fail-fast/plugin")(on, config);
},
},
...
#agoff was right, but there was another issue, so I'll explain here.
// support/index.ts
...
import 'cypress-fail-fast';
I added /plugin to the import, which wasn't needed.
And I did have to declare cypressFailFast in my setupNodeEvents.
I declare the plugin function like so:
setupNodeEvents(on, config) {
plugin(on, config);
},
plugin here refers to: import plugin from './cypress/plugins/index';
And in that file I declare:
export default function plugin(on, config) {
cypressFailFast(on, config);
...
Now everything works as expected:

process.env.NODE_ENV variables into scss via rollup

Is there a way to reference a process.env.NODE_ENV in a scss file by passing it to the sass-loader in postcss for rollup. If so anyone know how to go about this?
UPDATE1
Ok, so this is my rollup.config.js. I'm getting a weird issue where sometimes the $env is undefined and sometimes it is set to the right process.env.NODE_ENV
import serve from "rollup-plugin-serve";
import livereload from "rollup-plugin-livereload";
import babel from '#rollup/plugin-babel';
import { nodeResolve } from '#rollup/plugin-node-resolve';
import commonjs from '#rollup/plugin-commonjs';
import replace from '#rollup/plugin-replace';
import postcss from 'rollup-plugin-postcss';
import { uglify } from 'rollup-plugin-uglify';
const build = process.env.BUILD ? process.env.BUILD : 'development';
export default {
input: "src/index.js",
output: {
file: "dist/bundle.js",
sourcemap: true,
compact: true
},
plugins: [
postcss({
use: {
sass: {
data: "$env: " + process.env.NODE_ENV + ";"
}
},
}),
nodeResolve({
extensions: [".js"],
}),
replace({
'process.env.NODE_ENV': JSON.stringify(build)
}),
babel({
presets: ["#babel/preset-react"],
}),
commonjs(),
build === 'production' && uglify(),
serve({
verbose: true,
contentBase: ["", "public"],
host: "localhost",
port: 3000,
}),
build === 'development' &&
livereload({ watch: "dist" }),
]
};

Webpack4 with sass-loader, MiniCssExtractPlugin and uikit

I´m trying to setup a uitkit template with
webpack 4
sass loader
MiniCssExtractPlugin
uikit
What I would like to achieve is that a build automatically converts sass to css and that resulting css is injected into src/index.html.
webpack.config.js
const HtmlWebPackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
{
test: /\.html$/,
use: [
{
loader: "html-loader",
options: { minimize: true }
}
]
},
{
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: "css-loader",
options: {
modules: true,
sourceMap: true,
importLoader: 4
}
},
"sass-loader"
]}
]
},
plugins: [
new HtmlWebPackPlugin({
template: "./src/index.html",
filename: "./index.html"
}),
new MiniCssExtractPlugin({
filename: "[name].css",
chunkFilename: "[id].css"
})
]
};
index.js
import UIkit from 'uikit';
import Icons from 'uikit/dist/js/uikit-icons';
import style from "uikit/src/scss/uikit.scss"
UIkit.use(Icons);
Unfortunately a build fails with
ERROR in ./node_modules/uikit/src/scss/uikit.scss (./node_modules/css-loader??ref--6-1!./node_modules/sass-loader/lib/loader.js!./node_modules/uikit/src/scss/uikit.scss)
Module build failed (from ./node_modules/sass-loader/lib/loader.js):
$inverse-base-color: $inverse-global-color !default;
Undefined variable: "$inverse-global-color".
in new_proj/node_modules/uikit/src/scss/components/base.scss (line 607, column 49)
I would be thankful if one could explain What I´m doing wrong and why sass loader cannot find the variable $inverse-global-color.
I´ve found the answer. It´s working like this:
index.js
...
import style from "./main.scss"
...
main.scss
// 1. Your custom variables and variable overwrites.
$global-link-color: #DA7D02;
// 2. Import default variables and available mixins.
#import "uikit/src/scss/variables-theme.scss";
#import "uikit/src/scss/mixins-theme.scss";
// 3. Your custom mixin overwrites.
#mixin hook-card() { color: #000; }
// 4. Import UIkit.
#import "uikit/src/scss/uikit-theme.scss";

Webpack combine sass components into one css file

I have the following in my react component:
var webpack = require('webpack');
var path = require('path');
var BUILD_DIR = path.resolve(__dirname, 'public/js/');
var APP_DIR = path.resolve(__dirname, 'jsx');
var config = {
entry: APP_DIR + '/index.jsx',
output: {
path: BUILD_DIR,
filename: 'app.js'
},
module : {
loaders : [
{
test : /\.jsx?/,
include : APP_DIR,
loader : 'babel'
},
{
test: /\.scss$/,
loaders: ['style', 'css', 'sass']
},
{
test: /\.(eot|woff|woff2|ttf|svg|png)$/,
loader: 'url-loader?limit=30000&name=[name]-[hash].[ext]'
}
]
}
};
module.exports = config;
is it possible to combine all of the scss components into one .css file? Currently they are inserted inline because of me doing this:
import React from 'react';
import ReactDOM from 'react-dom'
import {render} from 'react-dom';
import axios from 'axios';
import Forms from './forms/forms.jsx';
import './../public/sass/typography.scss';
import './../public/sass/main.scss';
import './../public/sass/navigation.scss';
import './../public/sass/buttons.scss';
import './../public/sass/forms.scss';
import './../public/sass/icons.scss';
import './../public/sass/layout.scss';

How do I create a App shell that is cached for a Progressive Web app in a React App?

Currently, I use webpack to build a single JS file which represents my app. How do I split my React app UI shell from rest of the app logic, so that I can have the service Worker cache it?
My webpackpack config file looks like this, that generates a single index_bundle.js file(no css file):
import webpack from 'webpack'
import path from 'path'
import HtmlWebpackPlugin from 'html-webpack-plugin'
import autoprefixer from 'autoprefixer'
const LAUNCH_COMMAND = process.env.npm_lifecycle_event
const isProduction = LAUNCH_COMMAND === 'production'
process.env.BABEL_ENV = LAUNCH_COMMAND
const PATHS = {
root: path.join(__dirname),
app: path.join(__dirname, 'app'),
build: path.join(__dirname, 'dist')
}
const HTMLWebpackPluginConfig = new HtmlWebpackPlugin({
template: PATHS.app + '/index.html',
filename: 'index.html',
inject: 'body'
})
const productionPlugin = new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify('production')
}
})
const productionPlugin2 = new webpack.optimize.UglifyJsPlugin({
compressor: {
warnings: false
}
})
const base = {
entry: [
'babel-polyfill',
PATHS.app
],
output: {
path: PATHS.build,
filename: 'index_bundle.js'
},
module: {
loaders: [
{test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader'},
{test: /\.css$/, loader: 'style!css?sourceMap&modules&localIdentName=[name]__[local]___[hash:base64:5]&importLoader=1!postcss'}
]
},
postcss: [ autoprefixer({ browsers: ['last 2 versions'] }) ],
resolve: {
root: path.resolve('./app')
}
}
const developmentConfig = {
devtool: 'cheap-module-inline-source-map',
devServer: {
contentBase: PATHS.build,
historyApiFallback: true,
hot: true,
inline: true,
progress: true
},
plugins: [HTMLWebpackPluginConfig, new webpack.HotModuleReplacementPlugin()]
}
const productionConfig = {
devtool: 'cheap-module-source-map',
plugins: [HTMLWebpackPluginConfig, productionPlugin, productionPlugin2]
}
export default Object.assign({}, base, isProduction === true ? productionConfig : developmentConfig)
My "Instant Loading with Service Workers" talk from the Chrome Dev Summit 2015 covers creating a PWA using the App Shell + dynamic model, powered by React.
The code sample for it is part of the sw-precache library's repo: https://github.com/GoogleChrome/sw-precache/tree/master/app-shell-demo
(It's not necessarily the most idiomatic React code in the world, but the general concepts, especially when it comes to the service worker implementation, should hold.)

Resources