问题
I was working on a upgrade from Angular v4 to v7. There are some breaking changes due to the .angular-cli.json to angular.json and their structure. And then also upgrading the versions of angular and webpack has its impact.
In Angular 4 it has worked fine with the custom webpack builder but upgrading to v7 has its complications. It is also worth mentioning that trying the build without any @imports
in the scss on the node_modules that I use does work as expected too. So I see that the issue comes with the path to/from the webpack.
The main issue we have right now is that the sass-loader is compaining about the @import 'path/to/file'
that it doesn't find it and then fails the build.
Doing ng serve
and ng build
does work without any problem, but doing the build with the custom webpack it does fail because it doesn't find the path.
The error I get is:
ERROR in Module build failed (from ./node_modules/sass-loader/lib/loader.js): @import '../../styles/src/abstracts/_mixins.scss"; ^ File to import not found or unreadable: '../../styles/src/abstracts/_mixins.scss"; Parent style sheet: stdin in /Path/to/project (line 4, column 1)
I have also tried doing npm link
from the package from my local machine to the node_modules without any progress.
The packages are components that I import in my projects, it is only packages with components and its scss.
The webpack config files looks like this:
* webpack.config.app.prod.js *
var webpackMerge = require('webpack-merge');
var prod = require('./webpack.config.prod');
var AotPlugin = require('@ngtools/webpack').AngularCompilerPlugin;
module.exports = webpackMerge.strategy({
plugins: 'prepend'
})(prod.config, {
entry: './src/main-wp.editor.aot.ts',
output: {
filename: 'editor.bundle.js',
chunkFilename: '[id].chunk.js',
library: '_' + 'child',
libraryTarget: 'jsonp'
},
plugins: [
new AotPlugin({
tsConfigPath: 'tsconfig.aot.json',
entryModule: './src/app/modules/app.module#EditorModule',
debug: true
})
]
});
* webpack.config.prod.js *
var path = require('path');
var webpack = require('webpack');
var webpackMerge = require('webpack-merge');
var commonConfig = require('./webpack.config.common');
var UglifyJsPlugin = require("uglifyjs-3-webpack-plugin");
module.exports = {
config: webpackMerge(commonConfig, {
output: {
path: path.resolve(__dirname, 'dist'),
publicPath: '/',
filename: 'bundle.js',
chunkFilename: '[id].[hash].chunk.js'
},
module: {
rules: [
{
test: /\.ts$/,
use: ['@ngtools/webpack']
},
{
test: /\.js$/,
loader: '@angular-devkit/build-optimizer/webpack-loader',
options: {
sourceMap: false
}
}
]
},
plugins: [
new UglifyJsPlugin({
uglifyOptions: {
warnings: false,
ie8: false,
output: {
comments: false
}
}
})
]
}),
buildPath: function root(args) {
var _root = path.resolve(__dirname);
args = Array.prototype.slice.call(arguments, 0);
return path.join.apply(path, [_root].concat(args));
}
};
* webpack.config.common.js *
var HtmlWebpackPlugin = require('html-webpack-plugin');
var glob = require("glob");
var path = require('path');
module.exports = {
entry: './src/main.ts',
resolve: {
extensions: ['.js', '.ts']
},
module: {
rules: [
{
test: /\.html$/,
loaders: ['html-loader']
},
{
test: /\.scss$/,
use: [
{
loader: "to-string-loader"
},
{
loader: "css-loader", // translates CSS into CommonJS
options: {
sourceMap: true
}
},
{
loader: "sass-loader", // compiles Sass to CSS
options: {
sourceMap: true,
includePaths: glob.sync(
path.join(__dirname, '**/node_modules/@mypackage/styles/src/abstracts')
).map((dir) => path.dirname(dir)),
// includePaths: [path.resolve("node_modules/@mypackage")],
// includePaths: [
// path.resolve('../node_modules')
// ]
}
}
]
}
],
exprContextCritical: false
},
plugins: [
new HtmlWebpackPlugin({
template: 'src/index.html'
})
]
};
Versions I use for this.
"@angular/compiler-cli": "7.2.15"
"uglifyjs-3-webpack-plugin": "1.2.4"
"@angular-builders/custom-webpack": "7.4.3"
"@ngtools/webpack": "7.0.7",
"@types/node": "8.9.5"
"node-sass": "4.5.3"
"sass-loader": "7.3.1"
"to-string-loader": "1.1.5"
"ts-node": "7.0.1"
"typescript": "3.2.4"
"webpack": "4.29.0"
"webpack-cli": "3.3.10"
"webpack-merge": "4.2.2"
And node 8.9.5 with npm 5.5.1
Thanks!
回答1:
I had the same issue and I resolved it with sass-loader
applying the following rule for scss
the webpack.config.common.js
:
{
test: /\.component\.(css|sass|scss)$/,
use: [
'to-string-loader',
'css-loader',
{
loader: 'sass-loader',
options: {
sassOptions: {
importer: url => {
if (url.startsWith('@angular/')) {
return {
file: path.resolve(`./node_modules/${url}`),
};
}
return null;
},
},
}
}
]
}
If you have another library in node_module
that you need to use you can add another else if
statement:
Example, let's say I have a custom library my-library
in node_modules
and I want to access to: node_modules/my-library/style.scss
so I have to add the following else if
statement:
{
test: /\.component\.(css|sass|scss)$/,
use: [
'to-string-loader',
'css-loader',
{
loader: 'sass-loader',
options: {
sassOptions: {
importer: url => {
if (url.startsWith('@angular/')) {
return {
file: path.resolve(`./node_modules/${url}`),
};
else if (url.startsWith('my-library/')) {
return {
file: path.resolve(`./node_modules/${url}`),
};
}
return null;
},
},
}
}
]
}
Take in count that this was my project structure:
node_modules
dist
config
- webpack.common.js
- webpack.dev.js
- webpack.prod.js
- webpack.test.js
src
- app
- app-routing.module.ts
- app.component.html
- app.component.scss
- app.component.ts
- app.module.ts
- index.ts
- index.html
- main.browser.ts
- polyfills.browser.ts
angular.json
package.json
postcss.config.js
tsconfig.json
tsconfig.webpack.json
webpack.config.js
Let me know if this works for you.
来源:https://stackoverflow.com/questions/59901516/webpack-4-build-with-angular-7-gives-problem-with-the-sass-loader-when-trying-to