I am migrating from gulp/jspm to webpack. Everything is seemingly going fine by our SASS. In gulp our task looks like so:
var gulp = require('gulp');
var sourcemaps = require('gulp-sourcemaps');
var sass = require('gulp-sass');
var autoprefixer = require('autoprefixer');
var paths = require('../paths');
var flatten = require('gulp-flatten');
var postcss = require('gulp-postcss');
gulp.task('build-sass', () => {
return gulp.src(paths.sassSource)
.pipe(sourcemaps.init())
.pipe(sass().on('error', sass.logError))
.pipe(postcss([autoprefixer()]))
.pipe(flatten())
.pipe(sourcemaps.write('/maps'))
.pipe(gulp.dest(paths.output + 'css'));
});
And thus works perfectly. This is my current webpack config for SASS:
{
test: /\.scss$/,
loader: ExtractTextPlugin.extract({
fallbackLoader: 'style-loader',
loader: 'css-loader?sourceMap!postcss-loader!sass-loader?sourceMap',
}),
},
And in the plugins I have:
new ExtractTextPlugin({
filename: 'global.css',
allChunks: true,
}),
The problem is when I run webpack I get these SASS errors:
ERROR in ./~/css-loader?sourceMap!./~/postcss-loader!./~/sass-loader?sourceMap!./src/sass/base/_QB4-variables.scss
Module build failed:
$never-signed-in: $gray-light;
^
Undefined variable: "$gray-light".
in /Users/allen/work/TwentyTwenty.QualBoard.Web/src/sass/base/_QB4-variables.scss (line 31, column 19)
I am getting tons of those type of errors which I don't understand since the gulp sass tool never threw those errors before. I feel like some configuration is missing.
In my main.js file I was missing my sass include. Thus it was just compiling all that sass but with no particular order.
Related
I have created an app which uses Rails and a React front-end (rails new my-app --webpack=react)
I've worked with Rails and React separately before but never when integrated this way.
As the app is served on rails s, my understanding is that this is essentially working as a rails app which is rendering React components, so I believe be that the environment variables would be defined in config/application.yml rather than a .env, but I have tried both and can't get access to them in the React components
What I have tried
variables in .env and application.yml
dotenv-webpack
webpack DefinePlugin
adding my env files in config/webpack/environment.js
Prefixing with REACT_APP
Hardcoding the variable into the webpack config
I'm running the rails server as well as ./bin/webpack-dev-server, and also run "webpack --config webpack.config.js" before starting the servers.
My webpack.config.js
const Dotenv = require('dotenv-webpack');
const webpack = require('webpack');
const path = require('path');
module.exports = {
entry: path.resolve(__dirname, '') + '/app/javascript/packs/index.jsx',
plugins: [
new Dotenv(),
new webpack.DefinePlugin({
PRODUCTION: JSON.stringify(true),
VERSION: JSON.stringify('5fa3b9'),
BROWSER_SUPPORTS_HTML5: true,
TWO: '1+1',
'typeof window': JSON.stringify('object'),
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
'process.env.REACT_APP_LAST_FM_API_KEY': JSON.stringify('myApiKeyfs89fs08a0')
})
],
module: {
rules: [
{ test: /\.jsx$/, use: {loader:'babel-loader'} },
{ test: /\.js$/, use: {loader:'babel-loader'} }
]
},
node: {fs:"empty"},
output: {
publicPath: '/'
}
};
In the end, I didn't need to do any of the above things. I just needed the .env file and to add
const dotenv = require('dotenv')
dotenv.config()
to my config/webpack/development.js
I am using Rails 5 with webpack, trying to compile for production because the assets don't show up in production.
If I try NODE_ENV=production rake webpacker:compile, then it hangs at Compiling....
After reading Compiling in production fails silently and isn't verbose enough, I tried NODE_ENV=production bin/webpack --progress --config config/webpack/production.js. It hung at 78% [0] chunk asset optimization TerserPlugin
I read this https://fontawesome.com/how-to-use/with-the-api/other/tree-shaking#issues, but I'm not sure how to switch Rails webpack to use Babel Minify instead of Terser.
Any help changing Rails to use the Babel Minify plugin would be greatly appreciated.
You'd need to make the change in the environment you'd like to use Babel Minify with.
If it's for the production environment, your config/webpack/production.js needs to look similar to:
process.env.NODE_ENV = process.env.NODE_ENV || 'production'
const environment = require('./environment')
const BabelMinifyPlugin = require('babel-minify-webpack-plugin')
environment.config.optimization.minimizer = [ new BabelMinifyPlugin() ]
module.exports = environment.toWebpackConfig()
This assumes you added babel-minify-webpack-plugin as a dependency in your package.json file.
If you want to try disabling collapse_vars like the linked article points out in option 3, your config file should look similar to:
process.env.NODE_ENV = process.env.NODE_ENV || 'production'
const environment = require('./environment')
const UglifyJSPlugin = require("uglifyjs-webpack-plugin")
environment.config.optimization.minimizer = [
new UglifyJSPlugin({
uglifyOptions: {
collapse_vars: false
}
})
]
module.exports = environment.toWebpackConfig()
This assumes you added uglifyjs-webpack-plugin as a dependency in your package.json file.
I also had a problem with erb-loader. Found the solution in this comment. There is some problem with erb-loader and spring interaction which causes the freeze.
To fix it, just need to add
env: {
...process.env,
DISABLE_SPRING: 1,
}
to options in erb-loader config(config/webpack/loaders/erb.js),, so the entire config looks like this:
module.exports = {
test: /\.erb$/,
enforce: 'pre',
exclude: /node_modules/,
use: [{
loader: 'rails-erb-loader',
options: {
runner: (/^win/.test(process.platform) ? 'ruby ' : '') + 'bin/rails runner',
env: {
...process.env,
DISABLE_SPRING: 1,
},
}
}]
}
I think I may have been running into an issue similar to this one, Compiling never completes Rails 5.2, ERB and compile: true. I removed the erb loader from my project and RAILS_ENV=production rake assets:precompile completes. I also no longer get warnings about chunk size.
I've just started experimenting with Webpacker within an existing app.
From all that I've read, my understanding is that Webpacker and Sprockets can co-exist, and that libraries compiled in Webpacker (e.g., jquery) can be made available to Sprokets via global variables.
But all my jquery in the asset pipeline are raising ReferenceError: Can't find variable: $
Have I misunderstood, or is there a bug in my code?
I've added jquery
yarn add jquery
and assigned the variables in environment.js
const { environment } = require('#rails/webpacker');
const webpack = require('webpack');
environment.plugins.prepend('Provide', new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery'
}));
module.exports = environment;
this works:
#javascript/packs/application.js
$(function () {
console.log('Hello World from Webpacker via JQUERY');
});
this does not
#assets/javascripts/application.js
$(function () {
console.log('Hello World from Sprockets via JQUERY');
});
# ReferenceError: Can't find variable: $
What is the expected behaviour?
In the end it is relatively easy to expose jQuery to global from within webpacker. But finding documentation on how to do this was very difficult! Hopefully, this can save someone else a search.
Add expose-loader
yarn add expose-loader -D
And then add the following configuration to config/webpack/environment.js
environment.loaders.append('expose', {
test: require.resolve('jquery'),
use: [{
loader: 'expose-loader',
options: '$'
}, {
loader: 'expose-loader',
options: 'jQuery',
}]
})
I was then able to remove jquery from the asset pipeline, restart the server, and all my remaining jquery functions within sprockets continue to function as expected.
I use Webpack 4 in a project where I only need to compile and bundle styles so far. There's no Javascript.
Here's the config I have:
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
entry: {
'css/bundle': path.resolve(__dirname, 'static/scss/index.scss'),
},
output: {
path: path.resolve(__dirname, 'static'),
},
module: {
rules: [
{
test: /\.s[ac]ss$/,
include: path.resolve(__dirname, 'static/scss'),
use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader'],
},
],
},
plugins: [
new MiniCssExtractPlugin(),
],
};
The problem is that it outputs two files: bundle.css and bundle.js. Is there a way to configure Webpack so that it doesn't output the Javascript bundle? I tried to navigate the docs, tried a dozen different things, but it didn't really work.
One important note here is that if I remove the css-loader, bundling fails. So while css-loader is most likely responsible for outputting the bundle.js file, I'm not entirely sure how to avoid using it.
webpack-extraneous-file-cleanup-plugin has no effect with webpack 4.12.0.
I can suggest to remove bundle.js manually with on-build-webpack plugin:
var WebpackOnBuildPlugin = require('on-build-webpack');
// ...
plugins: [
// ...
new WebpackOnBuildPlugin(function () {
fs.unlinkSync(path.join('path/to/build', 'bundle.js'));
}),
],
March 2021:
In Webpack 5, on-build-webpack plugin did not work for me.
I found this:
Webpack Shell Plugin Next
The project I’m working on we’re using Webpack 5 as a build tool for a CSS pattern library. Therefore, we didn’t need the main.js in our dist.
Run npm i -D webpack-shell-plugin-next
Then in webpack.config.ts (just showing the pertinent parts):
import WebpackShellPluginNext from "webpack-shell-plugin-next";
module.exports = {
output: {
path: path.resolve(__dirname, "static/dist")
},
plugins: [
// Run commands before or after webpack 5 builds:
new WebpackShellPluginNext({
onBuildEnd: {
scripts: [
() => {
fs.unlinkSync(path.join(config.output.path, "main.js"));
}
]
}
})
]
};
export default config;
Unfortunately, this is just the way that webpack currently works. However, we are not alone in this problem! There's a plugin to cleanup any unwanted files:
install the plugin:
yarn add webpack-extraneous-file-cleanup-plugin -D
and then in your config:
const ExtraneousFileCleanupPlugin = require('webpack-extraneous-file-cleanup-plugin');
plugins: [
new ExtraneousFileCleanupPlugin({
extensions: ['.js'],
minBytes: 1024,
paths: ['./static']
}),
]
I simply delete the unneeded output with rm in package.json:
"scripts": {
"build": "npm run clean && webpack -p && rm ./dist/unneeded.js"
},
The webpack-remove-empty-scripts plugin, compatible with webpack 5, cover the current issue. It remove unexpected empty js file.
Having a first go at webpack.
In my root directory I have my main.js entry point and am also checking for .js and .scss files
It does compile the main.js file.
Webpack cannot seem to find any other .scss or .js files. What have I done wrong.
Full config below:
var webpack = require('webpack');
var path = require('path');
let ExtractTextPlugin = require("extract-text-webpack-plugin");
var webpack = require('webpack');
var path = require('path');
let ExtractTextPlugin = require("extract-text-webpack-plugin");
module.exports = {
entry: './main.js',
output: {
path: path.resolve(__dirname, './dist3'),
filename: 'bundle5.js'
},
module: {
rules: [
{ test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader?presets[]=es2015",
},
{
test:/\.scss$/,
use: ExtractTextPlugin.extract({
use: ['css-loader', 'sass-loader'],
fallback: 'style-loader',
})
},
]
},
plugins: [
//new webpack.optimize.UglifyJsPlugin(),
new ExtractTextPlugin('ross.css')
]
};
Webpack does not just include every file that is in your project, but instead starts from the entry point(s) and includes everything that is required in these files and their dependencies. If you want files to be included in your bundle you import them, even scss or other non-JavaScript files, and the loaders that match some rules will transform them to valid JavaScript. For example you can import an .scss file in JavaScript:
import './styles.scss';
You can also have multiple entry points that will add them with all their dependencies into the bundle. Take a look at the official docs for entry points: https://webpack.js.org/concepts/entry-points/
The loaders you define in module.rules just tell webpack how to process imports that match the regular expression you're using. For more information see: https://webpack.js.org/concepts/loaders/