Webpack file-loader with sass-loader - node.js

I am new to nodejs and get a problem when trying to use sass with it.
The following information is just fictional, but it represents the
actual condition.
THE SCENARIO:
I have the following folder structure:
frontend/
- scss/
- style.scss
- main.js
webpack.config.js
Goal:
I want to compile the style.scss to style.css using webpack and put it inside dist/frontend/css/ directory, so it should be resulting this path: dist/frontend/css/style.css and create the following folder structure:
dist/
- frontend/
- scss/
- style.scs
- main.js
frontend/
- scss/
- style.scss
- main.js
webpack.config.js
THE CODES:
main.js
import `style from "./scss/style.scss";`
webpack.config.js
module.exports = {
mode: "development",
entry: {
main: "./frontend/main.js"
},
output: {
path: path.join(__dirname, "/dist/frontend"),
publicPath: "/",
filename: "[name].js"
},
module: {
rules: [
{
test: /\.(s*)css$/,
use: [
{
loader: "file-loader",
options: {
name: "css/[name].[ext]"
}
},
"style-loader/url",
"css-loader?-url",
"sass-loader"
]
}
]
}
THE RESULT:
I get this message:
Module not found: Error: Can't resolve './scss/style.scss' in 'E:\project_name\frontend'
THE QUESTIONS
Why is that happening?
What is the correct codes to achieve the Goal?

As the message said, this path is not valid: './scss/style.scss'. There are typo when defining the path. The folder is supposed to be sass instead of scss.
The following configuration will work to achieve the Goal mentioned in the question:
module: {
rules: [
{
test: /\.(s*)css$/,
use: [
"style-loader/url",
{
loader: "file-loader",
options: {
name: "css/[name].css"
}
},
"sass-loader"
]
}
]
}
It works like Mini CSS Extract Plugin, but does not generating additional .js files for each .css file when used to convert multiple .scss files into different .css files.

Related

My tsconfig.json cannot find a module in my node_modules directory, not sure what is wrong

I have the following hierarchy:
dist/
|- BuildTasks/
|- CustomTask/
- CustomTask.js
node_modules/
source/
|- BuildTasks/
|- CustomTask/
- CustomTask.ts
- tsconfig.json
Additionally, I am trying to create a VSTS Task extension for internal (private) usage. Originally, I had my tsconfig.json at my root directory, and everything worked just fine on my local machine. The problem is that a VSTS Extension requires all the files to be included in the same directory as the task folder itself. See https://github.com/Microsoft/vsts-task-lib/issues/274 for more information:
you need to publish a self contained task folder. the agent doesnt run
npm install to restore your dependencies.
Originally, I had a this problem solved by include a step to copy the entire node_modules directory into each Task folder, in this case my CustomTask folder which contains my JS file. But, this seems a bit much considering that not every task I am writing has the same module requirements.
My idea was to create a tsconfig.json in each of the Task folders which would specify to create a single output file containing all of the dependent modules, but unfortunately it is not working:
{
"compilerOptions": {
"baseUrl": ".",
"target": "ES6",
"module": "system",
"strict": true,
"rootDir": ".",
"outFile": "../../../dist/BuildTasks/CustomTask/CustomTask.js",
"paths": {
"*" : ["../../../node_modules/*"]
}
}
}
Prior to adding the "paths", I was getting the following errors:
error TS2307: Cannot find module 'vsts-task-lib/task'.
error TS2307: Cannot find module 'moment'.
After adding the paths, I still get the error that it cannot find the module 'moment', which is in my node_modules directory. Also, when I look at the output JS it seems that it didn't include the 'vsts-tasks-lib' code necessary, maybe because it still had an error in regards to the 'moment' module? Not sure what I missed?
Using webpack to compile JavaScript modules, simple sample:
webpack.config.js:
const path = require('path');
module.exports = {
entry: './testtask.ts',
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/
}
]
},
resolve: {
extensions: ['.tsx', '.ts', '.js']
},
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
},
node: {
fs: 'empty'
},
target: 'node'
};
After that, there are just bundle.js and task.json in task folder.
Update: sample code in testtask.ts:
import tl = require('vsts-task-lib/task');
import fs = require('fs');
console.log('Set variable================');
tl.setVariable('varCode1', 'code1');
tl.setTaskVariable('varTaskCode1', 'taskCode1');
var taskVariables = tl.getVariables();
console.log("variables are:");
for (var taskVariable of taskVariables) {
console.log(taskVariable.name);
console.log(taskVariable.value);
}
console.log('##vso[task.setvariable variable=LogCode1;]LogCode1');
console.log('end========================');
console.log('current path is:' + __dirname);
fs.appendFile('TextFile1.txt', 'data to append', function (err) {
if (err) throw err;
console.log('Saved!');
});
console.log('configure file path:' + process.env.myconfig);
console.log('configure file path2:' + process.env.myconfig2);

Typescript Definition Files in Webpack

Okay, so I have a Typescript definition file model.d.ts. It contains definitions for the classes used in my business logic, so that I can have strong typing in my Vue.js files.
I have a Vue.js template person.vue, with a code section that looks like this:
<script lang="ts">
import axios from "axios";
import * as _ from "lodash";
import * as model from "model";
// ...
</script>
But when I try to build this with Webpack, I run into problems:
ERROR in I:\git\myapp\src\component\person-page\person.vue.ts
[tsl] ERROR in I:\git\myapp\src\component\person-page\person.vue.ts(27,24)
TS2307: Cannot find module 'model'.
ERROR in ../myapp/node_modules/ts-loader!../myapp/node_modules/vue-loader/lib/selector.js?type=script&index=0&bustCache!../myapp/src/component/person-page/person.vue
Module not found: Error: Can't resolve 'model' in 'I:\git\myapp\src\component\person-page'
# ../myapp/node_modules/ts-loader!../myapp/node_modules/vue-loader/lib/selector.js?type=script&index=0&bustCache!../myapp/src/component/person-page/person.vue 10:14-30
# ../myapp/src/component/person-page/person.vue
# ../myapp/src/main.ts
# multi webpack-hot-middleware/client ./src/main.ts
I'm using ts-loader, and the relevant parts of my webpack.config.js look like this:
module.exports = {
// ...
module: {
rules: [
// ...
{
test: /.ts$/,
use: {
loader: "ts-loader", options: {
appendTsSuffixTo: [/\.vue$/]
}
},
exclude: /node_modules/
},
// ...
{
test: /\.vue$/,
loader: "vue-loader"
}
]
},
resolve: {
extensions: [".ts", ".js", ".vue", ".json"],
alias: {
"vue$": "vue/dist/vue.esm.js"
}
}
};
Why doesn't my definition file work, and how can I make it so that it can be used in person.vue?
I think you have a problem with your path. "model" should point to the complete path to the model.d.ts without the file extensions.

webpack multiple output path, limit public access, or custom index.html?

I am using node-express, with typescript.
my folder is setup as follows:
.dist
public
public.js
index.html
server.js
node_modules
src
classes
namespace1
module1
public
app - all angular files.
main.ts
routes
index.ts
app.ts
package.json
tsconfig.json
webpack.config.js
Now, I need webpack to output 2 files to /public/public.js and /server.js at .dist folder. nodejs will then run from .dist/server.js, and I want to separate public.js to prevent client to access server.js
I also use html-webpack-plugin to generate html files.
I have tried using a little hack like
entry: {
"server": "./src/app.ts",
"public/public": "./src/public/main.ts"
}
but then html-webpack-plugin made index.html to load script from /public/public.js instead of public.js
Now, I think we can solve this in 3 way.
Let server.js send public.js using http://localhost/public.js, but it will make managing static folder a little bit complicated. but I will think some way to trick it. Question: how to serve public.js via server.js?
Set entry to "public": "./src/public/main.ts". Question: how to put that public.js into public folder?
Setup html-webpack-plugin to load from /public.js instead of /public/public.js and make index.html inside /public folder. As of now, html-webpack-plugin generates <script type="text/javascript" src="../public/polyfill.js"></script><script type="text/javascript" src="../public/public.js"></script></body> where is should make <script type="text/javascript" src="/polyfill.js"></script><script type="text/javascript" src="/public.js"></script></body>
Question: How to do that?
Or is there any other idea to solve this? I am open to any suggestion.
Thank you
I think I can answer scenarios 2 and 3.
2- Apart of setting up entry points, you can set up some output configuration. http://webpack.github.io/docs/configuration.html#output
3- Also you could use copy webpack plugin to copy the files you need into your public folder.
https://github.com/kevlened/copy-webpack-plugin
I do it in one of my projects, this is the code that I add on the webpack config file:
new CopyWebpackPlugin([
{from: __dirname + '/src/public'}
])
Hope this helps.
Regards.
I managed by using this config.
module.exports = [
{
entry: "./src/app.ts",
output: {
filename: "server.js",
path: __dirname + "/dist"
},
target: "node",
resolve: {
extensions: ['.ts', '.js', '.tsx', '.jsx']
},
node: {
__dirname: false
},
module: { // all modules here for server
}
}, {
entry: "./src/public/main.ts",
output: {
filename: "bundle.js",
path: __dirname + "/dist/public"
},
target: "web",
plugins: [
new htmlPlugin({
filename: 'index.html'
})
],
resolve: {
extensions: ['.ts', '.js', '.tsx', '.jsx']
},
module: { // all your modules here.
}
}
]

how to make images directory and sub directory with webpack.

I am using Nodejs for web application development and webpack as bundler.My code is here:
Directory Structure is:
main.js
src
- js
- styles
- images
-logo.png
-clients_logo
- client_logo1.png
- client_logo2.png
-----------------------------------
public (Use for output)
- js
- css
- images
webpack.config.js
module.exports = {
entry: './main.js',
output: { path: path.join(__dirname, './public/'), filename: './js/bundle.js' },
module: {
loaders: [
{ test: /\.(jpg|jpeg|gif|png)$/,loader:'url-loader?limit=1024&name=images/[name].[ext]' }
]
}
};
main.js
import './src/images/logo.png';
require.context('./src/images/clients_logo/', true);
when I am compile this code using webpack --progress --colors command out put is:
public
- images
- logo.png
- client_logo1.png
- client_logo2.png
But Required out put is:
public
- images
- logo.png
- clients_logo
- client_logo1.png
- client_logo2.png
I am also use
{ test: /\.(jpg|jpeg|gif|png)$/,loader:'url-loader?limit=1024&name=[path][name].[ext]?[hash]&context=/path' }
but it's out put is:
public
- images
- src
- images
- logo.png
- clients_logo
- client_logo1.png
- client_logo2.png
So any one to understand this problem and have solution for it,Please provide it.Thanks
[path] is the relative path of the sources, which in your case is src/images/logo.png and so on for the other images. With context the [path] becomes relative to that path. Setting context=src/ will change that [path] to images/logo.png, which is exactly what you want.
So you can change your config to:
{
test: /\.(jpg|jpeg|gif|png)$/,
loader: 'url-loader?limit=1024&name=[path][name].[ext]&context=src/'
}

Exclude all starting with x in requirejs module

I am "compiling" some files into one requirejs module. I have a configuration like this:
paths:
lib : "../lib"
angular: "../lib/angular"
modules: [
{
name : 'myApp'
exclude: ["lib/jquery", "lib/angular"]
}
]
(syntax is cofeescript)
I want to exclude all files located under "lib" (e.g. starting with lib/) in "myApp" module. I now I can write them one another one like this: ["lib/jquery", "lib/angular"] But more libs and modules will be added in the future so some kind of automatization would be nice.
Is there any way to tell require js that "everything under lib should be excluded on myApp module"? Somethink like this:
modules: [
{
name : 'myApp'
exclude: ["lib/*"]
}
]
I don't know of a wildcard syntax, but you can define the list of excluded files as their own module, and then exclude them by name in all future modules.
Sorry, don't speak coffeescript:
modules: [
{
name: 'core',
include: [ 'lib/jquery', 'lib/angular', 'lib/somethingelse' ]
},
{
name: 'module1',
exclude: [ 'core' ]
},
{
name: 'module2',
exclude: [ 'core' ]
}
]

Resources