How to configure webpack via vue-cli 3 to use sass - javascript

I'm building a vue app with vue-cli 3. I'd like to include sass files in my webpack build but the vue-cli abstracts away the webpack.config.js file. Instead we are to create a vue.config.js file and configure it with a set of instructions.
If I were configuring webpack.config.js, the following would work:
module.exports = {
module: {
rules: [
// ... other rules omitted
// this will apply to both plain `.scss` files
// AND `<style lang="scss">` blocks in `.vue` files
{
test: /\.scss$/,
use: [
'vue-style-loader',
'css-loader',
'sass-loader'
]
}
]
},
// plugin omitted
}
How should I configure my vue.config.js to achieve the same? Here is my best attempt:
module.exports = {
chainWebpack: config => {
config.module
.rule('scss')
.test(/\.scss$/)
.use('vue-style-loader')
.loader('vue-style-loader')
.use('css-loader')
.loader('css-loader')
.use('sass-loader')
.loader('sass-loader')
.end();
}
};
This fails with the message
ERROR TypeError: config.module.rule(...).test(...).use(...).loader(...).use is not a function

If you are using vue cli 3 then just run the following in your project root directory:
vue add style-resources-loader

Related

How to save WebPack output files to another place automatically after my project is built

We have a SDK project witch is depended by another two projects.
When we want to build whole application, firstly, we need to build SDK project and upload it. Then we can build another two projects after run npm install.
This time I want to add a script for developer. When I run the script in SDK project it I can save the built output files to another projects node_modules.
Here is my code.
package.json file:
{
...
"scripts": {
"build:dev": "webpack --mode=development",
...
}
...
}
webpack.config.js file:
let config = {
...
module: {
rules: [
{
test:/\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/
}
]
}
...
}
module.exports = (env, argv) => {
if(argv.mode === 'development') {
// We put all the projects in one repo
config.output.path = path.resolve(__dirname,'../another-project/node_modules/sdk/dist/bundle')
}
}
And at last we set outDir in tsconfig.json.
The problem is:
How to change the output file path for typescript declaration files by WebPack arguments?
How to save all the file to two places one time?
I figure out the last problem by using webpack -env xxx && webpack -env xxx. I just run script twice, maybe someone has better idear.
Now just one qusetion:
How to set the output file path for typescript declaration files dynamically?
webpack.config.js file:
let config = {
...,
module: {
rules: [
{
test:/\.tsx?$/,
use: 'ts-loader',
options: {
configFile: "tsconfig.server.json"
}
}
]
},
...
}
Then I can change configFlie in webpack module.
https://webpack.js.org/configuration/output/
module.exports = {
...
output: {
filename: "lib.js"
}
...
Configuring the out dir in typescript will not help you because webpack is the one responsible for compilation and will only use typescript for compilation after outputting the files itself.

Webpack 2 and SASS: A SASS script can't find its font dependencies when it is #imported to another SASS file

I want to dig into modern frontend development using Webpack 2 and Materialize. Because I might customize the style, I want to #import the Materialize SASS file into my own SASS file, so I can overwrite stuff. However, if I do that, Webpack 2 can't compile my SASS file anymore because it doesn't find the Materialize fonts.
This is my current webpack.config.js, copypasted from all over the internet:
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const extractSass = new ExtractTextPlugin({
filename: "style.css",
disable: process.env.NODE_ENV === "development"
});
module.exports = {
entry: './src/js/index.js',
output: {
path: __dirname + '/public/dist',
filename: 'app.js'
},
module: {
rules: [
{
test: /\.scss$/,
use: extractSass.extract({
use: [{
loader: "css-loader"
}, {
loader: "sass-loader"
}, {
loader: "resolve-url-loader"
}],
// use style-loader in development
fallback: "style-loader"
})
},
{
test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
loader: 'url-loader?limit=80000&mimetype=application/font-woff'
},
{
test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
loader: 'file-loader'
}
]
},
plugins: [
extractSass
]
};
I installed materialize-css via npm. If I put the following in my src/js/index.js file, the compilation works fine:
require('materialize-css/sass/materialize.scss');
I get the desired outputs in my public/dist directory (app.js, style.css and the font files that Materialize provides). But as I said, I want to import Materialize to my own SASS file, which looks something like this (src/scss/main.scss):
#import "~materialize-css/sass/materialize";
// ... overwrite some stuff here ...
Because of to the ~ in front of the filepath, the loader looks for the file in the node_modules directory, thus the materialize.scss file can be imported successfully.
I then have two possibilities to include my SASS file in my Webpack bundle: either change the require() call in my index.js to import that file instead of the materialize.scss file or change the entry key in my webpack.config.js to
entry: [
'./src/js/index.js',
'./src/scss/main.scss'
],
Either way, the compilation fails because Webpack cannot find the font files. This is one of the many errors that occur
ERROR in ./~/css-loader!./~/sass-loader/lib/loader.js!./~/resolve-url-loader!./src/scss/main.scss
Module not found: Error: Can't resolve '../fonts/roboto/Roboto-Thin.woff2' in 'C:\Users\Myname\Documents\Projects\webpack-test\src\scss'
# ./~/css-loader!./~/sass-loader/lib/loader.js!./~/resolve-url-loader!./src/scss/main.scss 6:75477-75521
# ./src/scss/main.scss
# multi ./src/js/index.js ./src/scss/main.scss
So this is where I am stuck. Why does the compilation work if I require() the Materialize SASS file directly? Why does it fail when I import the Materialize SASS file to my own SASS file? How do I have to change my Webpack config so that it can find the font files?
By accident I found out that materialize offers a variable to set the font path, so adjusting my own SASS file to this solved the problem
$roboto-font-path: "~materialize-css/fonts/roboto/" !default;
#import "~materialize-css/sass/materialize";
// ... my customizations ...

Webpack concatenate scss files

In my last project I used gulp to concat all .scss files from several folders into one .scss file. Next I was using sass to compile that singe .scss file into css.
gulp.task('styles', function () {
gulp.src('styles/**/*.scss')
.pipe(concat('style.scss'))
.pipe(gulp.dest('production/'))
.pipe(sass({outputStyle: 'expanded'}))
.pipe(gulp.dest('production/'))
.pipe(sass({outputStyle: 'compressed'}))
.pipe(rename('style-min.css'))
.pipe(gulp.dest('production/'));
});
Now I want to create exactly the same 'building process' with Webpack.
entry: {
"style": "./styles/**/*.scss",
"style.min": "./styles/**/*.scss"
},
output: {
path: __dirname,
filename: "[name].css"
},
plugins: [
new ExtractTextPlugin('[name].css')
],
module: {
loaders: [
//Sass file
{ test: /\.scss$/, loader: ExtractTextPlugin.extract('css!sass') }
]
}
Unfortunately Webpack don't understand ** and *.scss. Is there any solution to gain the same behavior?
PS I need to concat those files. I don't want to use any kind of Sass #imports etc.
For example, you could use node-glob package like this:
var glob = require('glob');
var styles = glob.sync('./styles/**/*.scss');
module.exports = {
entry: {
'style': styles,
...
You need to use loaders for all file types except javascript, to load using webpack. In your case you need sass-loader, css-loader, style-loader. Perform the below steps to make your scss work using webpack:
Install below dependencies
npm install sass-loader css-loader style-loader
Add the webpack.config.js
Webpack config
module.exports = {
module: {
loaders: [
{
test: /\.scss$/,
loaders: ["style", "css", "sass?config=otherSassLoaderConfig"]
}
]
},
otherSassLoaderConfig: {
}
};
Now just require your scss file as require('./style.scss') and it will be loaded
For a detailed refrence you can also take a look at: https://stackoverflow.com/a/26876311/3878940

How to place all the css code from .vue files into one .css file?

I'm starting VueJS, I started my code from the original Vue Loader Example and I tested running npm run dev or npm run build but a question emerge : Is there a way to place all the css from the components in one place (like styles.min.css).
I added bootstrap as dependencies in my package.json and but when I do a npm run build I can only find the build.js file in dist, that's all.
Thank you for your help.
There's a plugin for that
npm install extract-text-webpack-plugin --save-dev
and then configure it in your webpack.config.js
var ExtractTextPlugin = require("extract-text-webpack-plugin");
module.exports = {
// other options...
module: {
loaders: [
{
test: /\.vue$/,
loader: 'vue'
},
]
},
vue: {
loaders: {
css: ExtractTextPlugin.extract("css"),
// you can also include <style lang="less"> or other langauges
less: ExtractTextPlugin.extract("css!less")
}
},
plugins: [
new ExtractTextPlugin("style.css")
]
}

Webpack: node_modules/css/index.js didn't return a function

I'm trying out webpack for the first time and used this tutorial to get started and include react.js.
After finishing the steps and installing the style and css module I keep getting an error that the css module didn't return a function.
This is my index.jsx:
/** #jsx React.DOM */
'use strict';
require('../css/normalize.css');
var React = require('react');
var Hello = require('./Test/Hello');
React.render(<Hello />, document.getElementById('content'));
And my webpack config file:
module.exports = {
entry: './ui/src/index.jsx',
output: {
path: __dirname + '/build-ui',
filename: 'app.js', //this is the default name, so you can skip it
//at this directory our bundle file will be available
//make sure port 8090 is used when launching webpack-dev-server
publicPath: 'http://localhost:8090/assets'
},
module: {
loaders: [
{
//tell webpack to use jsx-loader for all *.jsx files
test: /\.jsx$/,
loader: 'jsx-loader?insertPragma=React.DOM&harmony'
},
{
test: /\.css$/,
loader: "style!css"
},
{
test: /\.scss$/,
loader: "style!css!sass"
}
]
},
externals: {
//don't bundle the 'react' npm package with our bundle.js
//but get it from a global 'React' variable
'react': 'React'
},
resolve: {
extensions: ['', '.js', '.jsx']
}
};
When webpack tries to bundle the project it always states the following error:
ERROR in Loader /Users/Johannes/Documents/Development/holmes/node_modules/css/index.js didn't return a function
# ./ui/src/index.jsx 5:0-31
I don't know what to do about that. Has anyone encountered that issue? And how can I solve it?
EDIT: My directory looks as follows:
holmes/
ui/
css/
normalize.css
src/
Test/
Hello.jsx
index.jsx
index.html
package.json
webpack.config.js
This error is caused by a css module inside node_modules. Since you've specified the css-loader in your config, webpack tries to lookup that loader inside node_modules and finds another module called css which doesn't look like a loader (hence the error message).
To avoid confusion you should simply add the -loader postfix to each loader. Omitting the -loader postfix is just a convenience feature by webpack, but unfortunately it's the culprit of that error in your case.
loaders: [
{
//tell webpack to use jsx-loader for all *.jsx files
test: /\.jsx$/,
loader: 'jsx-loader?insertPragma=React.DOM&harmony'
},
{
test: /\.css$/,
loader: "style-loader!css-loader"
},
{
test: /\.scss$/,
loader: "style-loader!css-loader!sass-loader"
}
Update: Starting with webpack 2, you can't omit the -loader postfix anymore. We decided to do this to prevent errors like this.
I had a similar issue with react-flexbox-grid. In my case, the solution was installing css-loader and style-loader npm modules:
npm install css-loader style-loader --save-dev
I also came across a similar issue using node-noop.
Fortunately, using null as a replacement worked when I added enzyme and react-addons-test-utils to a project.

Categories