I am new to webpack and attempting to learn it. I have been trying to copy my vendor js files and custom jquery scripts from src to dist using webpack. I have tried but I couldn't find any way.
So this is how my folder structure is:
Project_root_folder
node_modules/
package.json
src/
app/
app.js
img/
img1.png
css/
main.scss
js/
custom_slick.js
main.js
plugins/
jquery.min.js
slick.min.js
index.pug
about.pug
contact.pug
dist/
webpack.config.js
My webpack.config file
var path = require("path"),
src = path.resolve(__dirname, "src"),
dist = path.resolve(__dirname, "dist"),
webpack = require("webpack"),
HtmlWebpackPlugin = require("html-webpack-plugin"),
HtmlWebpackPugPlugin = require('html-webpack-pug-plugin'),
ExtractTextPlugin = require("extract-text-webpack-plugin"),
extractPlugin = new ExtractTextPlugin({
filename: "css/main.css"
});
module.exports = {
entry: src + "/app/app.js",
output: {
path: dist,
filename: "bundle.js",
publicPath: "/"
},
module: {
rules: [
{ //Convert .pug to .html
test: /\.pug$/,
loaders: ['file-loader?name=[name].html', 'pug-html-loader?pretty&exports=false']
},
{
test: /\.scss$/, //convert .scss to .css
use: extractPlugin.extract({
use: ["css-loader", "sass-loader?minimize=true"]
})
},
{
test: /..\js\$\.js$/, // move all .js files in js folder
use: [
{
loader: "file-loader",
options: {
name: "[name].js",
outputPath: "js/"
}
}
]
},
{
test: /..\js\plugins\.js$/,
use: [
{
loader: "file-loader",
options: {
name: "js/plugins/[name].js",
outputPath: "js/plugins/"
}
}
]
}
]
},
plugins: [
extractPlugin
]
}
App.js file
import '../css/main.scss';
require.context('../js/', true, /\.js$/); //require all js files in js folder
require.context('../js/plugins/', true, /\.js$/); // all js files in plugins folder which is inside js folder
function requirAll (r) { r.keys().forEach(r); }
requireAll(require.context('../', true, /\.pug$/));
Also when I run this config file, I noticed that only the script files with a suffix "-js" get copied and not any other js files included in js/ folder for example filename "main.js" doesn't get copied but if it were named "main-js.js" then it gets copied into my dist folder, and I am unable to copyfiles from plugins/ folder. I am unable to understand this.
I have tried every possible solution I could come across over Stack Overflow, GitHub and similar websites but none were helpful. Also I found webpack to be extremely confusing. Before moving to webpack, I had been using Gulp which I found a lot more helpful. I came across webpack and want to learn it but I am finding it extremely difficult.
Try to use Copy Webpack Plugin in order to copy files between folders.
I'm not sure the reason why you want to copy js files, webpack works like a tree dependency solver, so it should get an entry point (of the tree) and create a bundle that has the entire tree of dependencies.
Related
I have very basic webpack + mini-css-extract-plugin project (you can found it here).
Here is webpack.config.js:
const path = require("path");
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
resolve: {
modules: [path.resolve(process.cwd(), 'node_modules')]
},
module: {
rules: [
// file loader allows to copy file to the build folder and form proper url
// usually images are used from css files, see css loader below
{
test: /\.png$/,
exclude: /node_modules/,
use: [
{
loader: 'file-loader',
options: {
name: "_assets/[name].[ext]"
}
}
]
},
// css files are processed to copy any dependent resources like images
// then they copied to the build folder and inserted via link tag
{
test: /\.css$/i,
sideEffects: true,
exclude: /node_modules/,
// for tests we use simplified raw-loader for css files
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
// public path has changed so url(...) inside css files use relative pathes
// like: url(../_assets/image.png) instead of absolute urls
publicPath: '../',
}
},
'css-loader'
]
}
]
},
plugins: [
// plugin helps to properly process css files which are imported from the source code
new MiniCssExtractPlugin({
// Options similar to the same options in webpackOptions.output
// both options are optional
filename: '_assets/[name].css',
chunkFilename: '_assets/[id].css'
})
],
entry: {
'test': "./src/test"
},
output: {
path: path.resolve(process.cwd(), `public`),
publicPath: '',
filename: '[name].js',
chunkFilename: '_chunks/chunk.[name].js'
}
};
main entry file test.js:
import './css/testCss.css';
console.log('Loaded');
When i run webpack build i got the following output structure:
/
|-test.js
|-_assets/
| |-test.css
When i include this js bundle into html i would expect that test.js bundle will load test.css file dynamically but this is not the case - js bundle works ok, but css file is not loaded at all.
It is only loaded when i modify source of the test.js like so:
import('./css/testCss.css'); // <--------- NOTE: dynamic import here
console.log('Loaded');
in this case after webpack build i got the following output:
/
|-test.js
|-_assets/
| |-0.css
|-_chunks/
| |-chunk.0.js
and when i load this js bundle in html - it loads both chink.0.js and 0.css
MAIN QUESTION: Is dynamic import the only correct way to include css into my js files via mini-css-extract-plugin?
Because in documentation they say yo use normal static import like import "./test.css"
my environement info:
node version: v14.12.0
webpack version: 4.44.1 (also tested on 5.2.0)
mini-css-extract-plugin version 1.1.2
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 ...
I found this code online to create a webpack for react.. what exactly is happening here? I need something like this to be able to use react right? I'm quite confused.
const path = require('path');
const SRC_DIR = path.resolve(__dirname, 'client');
const BUILD_DIR = path.resolve(__dirname, 'client');
module.exports = {
entry: path.resolve(SRC_DIR, 'client-app.js'),
output: {
filename: 'bundle.js',
path: BUILD_DIR
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: [/node_modules/],
use: [{
loader: 'babel-loader',
options: { presets: ['es2015', 'react'] }
}],
}
]
}
}
Why is it asking me to please add some context? I am trying to add more details so that this question can be posted
The code above does the following:
It resolves the client folder inside your projects folder and saves it to SRC_DIR and BUILD_DIR.
It tells webpack to look for a file named client-app.js in the resolved client folder from step 1.
It tells webpack to output the bundles Javascript into the client folder from step 1 with the file name bundle.js.
It tells webpack to look for any imported or required .js and .jsx files beginning at client-app.js inside your project folder (while excluding files from node_modules unless explicitly imported) and load them into the bundle using the babel-loader with the presets to compile the code from es2015 react to es5.
I currently have a few variables in a js file and would like to put it in its own bundle outside of my main app.bundle.js.
config.js
export const url1= 'testing1';
export const url2= 'test2';
I have a very basic webpack like this and added the new entry(This is just an example)
module.exports = {
{
entry: {
app: [path.resolve(__dirname, './src/index.js')],
config: [path.resolve(__dirname, './config.js')] <---here
},
output: {
filename: '[name].js',
path: __dirname + '/built'
}
}
module.loaders: [
{
// "test" is commonly used to match the file extension
test: /\.jsx$/,
// "include" is commonly used to match the directories
include: [
path.resolve(__dirname, "app/src"),
path.resolve(__dirname, "app/test")
],
// "exclude" should be used to exclude exceptions
// try to prefer "include" when possible
// the "loader"
loader: "babel-loader"
}]
finally I have a src/file.js that wants to use the config.js (I'm currently doing this but i am not sure if this is correct)
import { url1, url2} from '../../config.js';
my app bundle will bundle all the js files expanded from my index.js(which is all my /src .js files).
My config.js is outside of the src folder however I want one of my js files from src to use those variables that I have set in the config.js.
My result does produce a conf.bundle.js with the variables but it also seems to be bundled into the app.bundle.js as well.
So now my question is how would I be able to use the config.bundle.js variables on my app.bundle.js without having a copy of config.js in the app.bundle.js
Adding CommonChunksPlugin solves this issue.
I'm currently using Webpack to pack our Angular2 application and i'm facing a problem.
I've read several documentations but I can't achieve how to copy some files in my output directory using the file loader.
Here is my current file hierarchy :
config
| - webpack.common.js
app
|- static
| - css
| - ...
| - fonts
| - ...
| - img
| - someimage.png
| - anotherimage.png
|- main.ts
and the (full) webpack.common.js :
var path = require("path")
var webpack = require("webpack")
var ExtractTextPlugin = require("extract-text-webpack-plugin")
var HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: {
app: './app/main.ts',
},
output: {
filename: 'js/[name].js',
path:'./built',
chunkFilename: 'bundles/[id].chunk.js'
},
module: {
loaders: [
{
test: /\.ts$/,
loader: 'ts',
exclude:'./out/'
},
{
test: /\.(jpe?g|png|gif|svg)$/i,
include: [
path.resolve(__dirname, '/app/static/img/'),
],
loader: 'file?name=[path][name].[ext]&context=./src',
}
]
},
resolve: {
extensions: ['', '.js', '.ts', '.gif']
},
plugins: [
new HtmlWebpackPlugin({
template: './index.html'
})
]
}
To execute webpack I play the command :
webpack --config Config/webpack.common.js --bail
The ts file are correctly transpilled into javascript and copied into the output directory, the index.html file is also present but there is none of my image files.
I think there is something wrong in my configuration file but I can't see what. I'm banging my head on it fore many hours so any help will be much appreciated.
Thank you
Creating separate entry point for images may not be what you want, depending on how you build CSS part of the project. As alternative you can copy static files with copy-webpack-plugin or grunt / gulp task.
You should use url-loader to load images. Sample code is given below.
{
module: {
loaders: [
{ test: /\.(jpe?g|png|gif|svg)$/i, loader: 'url?limit=10000!img?progressive=true' }
]
}
}
Are you referring the gif files or corresponding css/sass files inside your entry js file.
entry: {
app: './app/main.ts',
}
Webpack will load all the files which have a reference in the entry point. If all your files are not in one entry point. Then you can add multiple entry points as shown below.
entry: {
app: './app/main.ts',
image: './app/something.ts'
}
Also, i would put webpack.config.js file directly in the root directory to have better access to the whole ecosystem. Try moving it from config folder to root folder.