I'm trying to bundle up all my libraries and for the most part? It works.
However, Vue is not being included in the bundle (but everything else is). I can't figure out how to include Vue with the bundled JS from webpack.
My webpack.config.js looks like this:
const autoprefixer = require("autoprefixer");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const HtmlWebPackPlugin = require("html-webpack-plugin");
var path = require("path");
var Vue = require('vue').default;
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = {
watch: true,
mode: "production",
entry: "./static/myapp/src/js/index.js",
externals: {
moment: "moment",
},
resolve: {
alias: {
'vue$': 'vue/dist/vue.esm.js'
}
},
output: {
filename: "[name].[contenthash].js",
path: path.join(__dirname, "static/myapp/dist/js/"),
publicPath: "/static/myapp/dist/js/",
},
optimization: {
splitChunks: {
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all'
}
}
}
},
module: {
rules: [
{
test: /\.(scss)|(css)$/,
use: [
MiniCssExtractPlugin.loader,
{ loader: "css-loader", options: { sourceMap: true } },
{
loader: "postcss-loader",
},
"sass-loader",
],
},
{
test: require.resolve("jquery"),
loader: "expose-loader",
options: {
exposes: ["$", "jQuery"],
},
},
{
test: /\.(woff(2)?|ttf|eot|svg)(\?v=\d+\.\d+\.\d+)?$/,
use: [
{
loader: "file-loader",
options: {
name: "[name][hash].[ext]",
outputPath: "fonts/",
},
},
],
},
],
},
plugins: [
new BundleAnalyzerPlugin(),
new MiniCssExtractPlugin({
filename: "../css/[name].[contenthash].css",
}),
new CleanWebpackPlugin(),
new HtmlWebPackPlugin({
template: path.join(
__dirname,
"static/myapp/src/html/webpack_bundles.html"
),
filename: path.join(
__dirname,
"templates/myapp/webpack_bundles.html"
),
inject: false,
}),
],
};
In my index.js I have this:
import "../scss/commonground.scss";
import "../css/style.css";
import "bootstrap";
import "select2";
import "vue";
import "bootstrap-datepicker/dist/css/bootstrap-datepicker.min.css";
import "bootstrap-datepicker/dist/js/bootstrap-datepicker.min";
import "select2/dist/css/select2.css";
All the other libraries (bootstrap, select2, bootstrap-datepicker) get bundled up, the CSS gets bundled together nicely, etc.
The bundle getting created (main.<hash>.js) does not include vuejs. How can I get it to?
I can't figure out how to get it to include vuejs. Any thoughts? Or any ideas that stick out? I've ran through numerous tutorials and how-to's, but can't seem to figure out why this isn't working.
Related
I've never used Webpack before and I'm working on a project that's just vanilla JS and HTML. I'm having an issue accessing the values I set in .env. Here's my config.
const path = require("path");
const dotenv = require('dotenv');
var webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const Dotenv = require('dotenv-webpack');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = () => {
env = dotenv.config().parsed;
const envKeys = Object.keys(env).reduce((prev, next) => {
prev[`process.env.${next}`] = JSON.stringify(env[next]);
return prev;
}, {});
return {
entry: {
main: './src/index.js'
},
output: {
path: path.join(__dirname, '../build'),
filename: '[name].bundle.js'
},
mode: 'development',
devServer: {
contentBase: "./src/",
publicPath: "./src/",
compress: true,
port: 9000,
overlay: true,
disableHostCheck: true
},
devtool: 'inline-source-map',
resolve: {
alias: {
process: "process/browser"
}},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader'
}
},
{
test: /\.css$/,
use: [
'style-loader',
'css-loader'
]
},
{
test: /\.(png|svg|jpe?g|gif)$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'assets/'
}
}
]
},
{
test: /\.html$/,
use: {
loader: 'html-loader',
options: {
//attributes: ['img:src', ':data-src'],
minimize: true
}
}
}
]
},
plugins: [
new webpack.ProvidePlugin({
process: 'process/browser',
}),
new Dotenv(),
new webpack.DefinePlugin(envKeys),
new HtmlWebpackPlugin({
template: './src/index.html',
filename: 'index.html'
}),
]
}
};
As you can see, I'm using dotEnv, definePlugin, and even the dotEnv-webpack plugin. Unfortunately, none of these solutions seem to allow me to access process.env.originURL.
originURL=https://localhost:3000
I'm not importing or requiring anything in my javascript file, index.js. I'm assuming this should work, but the console tells me that process is undefined.
console.log(process.env.originURL);
How can I access process.env.originURL in my index.js?
It should work. Maybe you could try this version:
new Dotenv({ systemvars: true })
If it still doesn't work, please show your package.json, as well as you .env file (randomize the values of course). Is .env at the root of you app?
I would like to divide my scss styles into chunks. Therefore, I created a separate subpage.scss imported by subpage.js file (one of the entries). I use miniCssExtractPlugin to extract SCSS styles from JS and create style bundles for each file. I map them in my BundleConfig to specific style chunks referenced in HTML.
The whole process works for the main.js and main.scss but not for subpage.js and subpage.scss - it leaves styles in .js file and the styles are loaded twice (both from JS and from HTML). The only difference between these cases is that the main.js is loaded as an entry in webpack.config.js and subpage.js is loaded with the remaining entries in webpack.DefinePlugin().
Any idea why MiniCssExtractPlugin doesn't extract the styles from a .js file loaded using this method and extracts styles for the main entry correctly?
My webpack.config.js
const readEntries = require('./entries');
const path = require('path');
const webpack = require('webpack');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const VueLoaderPlugin = require('vue-loader/lib/plugin');
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const entries = readEntries('../Scripts/entries');
module.exports = (mode) => ({
name: 'name',
context: path.resolve(__dirname, '../Scripts'),
resolve: {
extensions: ['.js', '.json', '.html', '.vue'],
alias: {
'~': path.resolve(__dirname, '../Scripts'),
'vue$': 'vue/dist/vue.esm.js',
'#trackers': path.resolve(__dirname, '../Scripts/trackers')
},
},
entry: {
main: './main.js',
},
output: {
path: path.resolve(__dirname, '../Content/bundle'),
publicPath: '/Content/bundle/',
filename: '[name].bundle.js',
chunkFilename: process.env.NODE_ENV === 'production' ? '[id].js?v=[contenthash]' : '[name].js?v=[contenthash]'
},
plugins: [
new CleanWebpackPlugin(),
new webpack.ProgressPlugin(),
new webpack.DefinePlugin({
'process.env': {
'ENTRIES': JSON.stringify(entries),
'NODE_ENV': JSON.stringify(mode)
}
}),
new VueLoaderPlugin(),
new MiniCssExtractPlugin({
filename: '[contenthash].[name].bundle.css',
}),
new BundleAnalyzerPlugin({
openAnalyzer: false,
analyzerMode: 'static'
})
],
module: {
rules: [
{
test: require.resolve('vue'),
use: [
{
loader: `expose-loader`,
options: 'Vue'
}
]
},
{
test: /\.vue$/,
loader: 'vue-loader'
},
{
test: /\.(js)$/,
use: [
'babel-loader'
],
exclude: /node_modules/
},
{
test: /\.(png|jpg|gif|svg)$/,
loader: 'file-loader',
options: {
name: '[name].[ext]?[contenthash]'
}
},
{
test: /\.(sa|sc|c)ss$/,
use: [
{
loader: MiniCssExtractPlugin.loader
},
'css-loader',
'postcss-loader',
'sass-loader'
]
}
]
},
optimization: {
splitChunks: {
chunks: 'async'
}
},
performance: {
hints: false
},
externals: {
jquery: 'jQuery',
DM: 'DM'
},
stats: {
modules: false
},
target: 'web'
});
my BundleConfig:
public class BundleConfig
{
public static void RegisterBundles(BundleCollection bundles)
{
bundles.IgnoreList.Clear();
BundleTable.EnableOptimizations = true;
bundles.Add(new ScriptBundle("~/bundles/js/head").Include(
"~/Scripts/head.js"
));
bundles.Add(new Bundle("~/bundles/js/scripts").Include(
"~/Content/bundle/main.bundle.js"
));
bundles.Add(new StyleBundle("~/bundles/css/main").Include(
"~/Content/bundle/*main.bundle.css"
));
bundles.Add(new StyleBundle("~/bundles/css/trends").Include(
"~/Content/bundle/*trends.bundle.css"
));
}
}
I am using webpack and typescript in my SPA along with the oidc-client npm package.
which has a structure like this:
oidc-client.d.ts
oidc-client.js
oidc-client.rsa256.js
When I import the oidc-client in my typescript file as below:
import oidc from 'oidc-client';
I want to import the rsa256 version and not the standard version, but I am unsure how to do this.
in my webpack config I have tried to use the resolve function but not I am not sure how to use this properly:
const path = require('path');
const ForkTsChecker = require('fork-ts-checker-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const VueLoaderPlugin = require('vue-loader/lib/plugin');
const FileManagerPlugin = require('filemanager-webpack-plugin');
const shell = require('shelljs');
const outputFolder = 'dist';
const destinationFolder = '../SPA/content';
if (shell.test('-d', outputFolder)) {
shell.rm('-rf', `${outputFolder}`);
}
if (shell.test('-d', destinationFolder)) {
shell.rm('-rf', `${destinationFolder}`);
}
module.exports = (env, options) => {
//////////////////////////////////////
/////////// HELP /////////////////////
/////////////////////////////////////
resolve: {
oidc = path.resolve(__dirname, 'node_modules\\oidc-client\\dist\\oidc- client.rsa256.slim.min.js')
};
const legacy = GenerateConfig(options.mode, "legacy", { "browsers": "> 0.5%, IE 11" });
return [legacy];
}
function GenerateConfig(mode, name, targets) {
return {
entry: `./src/typescript/main.${name}.ts`,
output: {
filename: `main.${name}.js`,
path: path.resolve(__dirname, `${outputFolder}`),
publicPath: '/'
},
resolve: {
extensions: ['.js', '.ts']
},
stats: {
children: false
},
devtool: 'source-map',
module: {
rules: [
{
test: /\.ts\.html?$/i,
loader: 'vue-template-loader',
},
{
test: /\.vue$/i,
loader: 'vue-loader'
},
{
test: /\.ts$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: [
[
'#babel/env',
{
"useBuiltIns": "usage",
"corejs": { version: 3, proposals: true },
"targets": targets
}
],
"#babel/typescript"
],
plugins: [
"#babel/transform-typescript",
[
"#babel/proposal-decorators",
{
"legacy": true
}
],
"#babel/plugin-proposal-optional-chaining",
"#babel/plugin-proposal-nullish-coalescing-operator",
"#babel/proposal-class-properties",
"#babel/proposal-numeric-separator",
"babel-plugin-lodash",
]
}
}
}
]
},
devServer: {
contentBase: path.join(__dirname, outputFolder),
compress: true,
hot: true,
index: `index.${name}.html`,
open: 'chrome'
},
plugins: [
new ForkTsChecker({
vue: true
}),
new HtmlWebpackPlugin({
filename: `index.${name}.html`,
template: 'src/index.html',
title: 'Project Name'
}),
new MiniCssExtractPlugin({ filename: 'app.css', hot: true }),
new VueLoaderPlugin()
]
};
}
Please add an alias to specify the exact .js module you'd like to import, like this for example:
resolve: {
extensions: ['.ts','.js'],
modules: ['node_modules'],
alias: {
'oidc-client': 'oidc-client-js/dist/oidc-client.rsa256.slim'
}
}
If you don't specify an alias, webpack/ will follow node module resolution and we'll eventually find your module by going to
library oidc-client-js in node_modules and follow package.json main property which is "lib/oidc-client.min.js" and that's not what you want.
I'm trying to introduce Sass-loader to an existing project so as to be able to use Sass in my React components. I've set this up successfully before in my own boiler plates and had no issues but for some reason with the current configuration it doesn't seem to play. It doesn't give any errors but rather doesn't do anything with my .scss file i'm trying to import.
I can see that there is some loaders in the cssLoaders config for Webpack which could be the culprit but I am only targeting .scss/ .sass files with the rule
test: /\.s(a|c)ss$/
so I wouldn't have thought this would affect it at all.
I have webpack setup with a common file and one for development. Here are both those files:
webpack.common.js
const CleanWebpackPlugin = require('clean-webpack-plugin');
const HtmlWebPackPlugin = require('html-webpack-plugin');
const ErrorOverlayPlugin = require('error-overlay-webpack-plugin');
const webpack = require('webpack');
const path = require('path');
require('babel-polyfill');
const Dotenv = require('dotenv-webpack');
module.exports = {
entry: {
main: ['babel-polyfill', './src/index.js']
},
output: {
filename: '[name].[hash].js',
path: path.resolve('./dist')
},
module: {
rules: [
{
test: /\.js$/,
exclude: ['node_modules'],
use: [{ loader: 'babel-loader' }]
},
{
test: /\.s(a|c)ss$/,
use: [
{
loader: 'style-loader'
},
{
loader: 'css-loader'
},
{
loader: 'sass-loader'
}
]
},
{
test: /\.(png|jpg|gif|svg)$/,
use: [
{
loader: 'url-loader',
options: {
limit: 8192,
outputPath: 'images/'
}
}
]
},
{
test: /\.(woff(2)?|ttf|eot|otf)(\?v=\d+\.\d+\.\d+)?$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'fonts/'
}
}
]
}
]
},
plugins: [
new ErrorOverlayPlugin(),
new webpack.HotModuleReplacementPlugin(),
new HtmlWebPackPlugin({
template: 'index.html'
}),
new Dotenv(),
new CleanWebpackPlugin(['dist'])
]
};
And here is webpack.dev.js
const path = require('path');
const webpack = require('webpack');
const ProgressBarPlugin = require('progress-bar-webpack-plugin');
const CircularDependencyPlugin = require('circular-dependency-plugin');
const paths = require('../paths');
module.exports = require('./webpack.config.base')({
bail: false,
devtool: 'cheap-module-eval-source-map',
stats: 'errors-only',
performance: {
hints: false
},
entry: {
main: [
require.resolve('react-dev-utils/webpackHotDevClient'),
paths.appPolyfillsJs,
require.resolve('react-error-overlay'),
paths.appIndexJs
]
},
output: {
pathinfo: true,
filename: 'static/js/[name].js',
chunkFilename: 'static/js/[name].chunk.js',
devtoolModuleFilenameTemplate: info =>
path.resolve(info.absoluteResourcePath)
},
// Load the CSS in a style tag in development
cssLoaders: [
{
loader: require.resolve('style-loader'),
options: {
sourceMap: true
}
},
{
loader: require.resolve('css-loader'),
options: {
modules: false,
sourceMap: true,
importLoaders: 1
}
},
{
loader: require.resolve('postcss-loader'),
options: { sourceMap: true }
}
],
babelQuery: {
cacheDirectory: true
},
plugins: [].concat([
new ProgressBarPlugin(),
new webpack.HotModuleReplacementPlugin(),
new webpack.NamedModulesPlugin(),
new webpack.NoEmitOnErrorsPlugin(),
new CircularDependencyPlugin({
exclude: /a\.js|node_modules/,
failOnError: true
})
])
});
The part that I have added to the configuration is in webpack.common:
{
test: /\.s(a|c)ss$/,
use: [
{
loader: 'style-loader'
},
{
loader: 'css-loader'
},
{
loader: 'sass-loader'
}
]
},
I then just import it in the module like so:
import React, { PureComponent } from 'react';
import './test.scss';
...
Can anyone spot why the configuration is wrong?
The sass-loader requires node-sass and webpack as peerDependency.
Make sure node-sass is installed and edit the loader webpack.dev.js like so:
{
loader: "sass-loader",
options: {
includePaths: ["absolute/path/a", "absolute/path/b"]
}
}
I have setup hot reloading with react-hot-loader. In the console it looks like it works, but browser does not actually reload. Why is this?
Ignore the errors, I think they come from a plugin. It correctly detects I change App.jsx but the browser does not update unless I do a full refresh.
My webpack.config.js below:
const path = require("path")
const webpack = require("webpack")
const HtmlWebpackPlugin = require("html-webpack-plugin")
const ExtractTextPlugin = require("extract-text-webpack-plugin")
const context = path.resolve(__dirname, "src")
const {dependencies} = require("./package.json")
module.exports = {
context,
entry: {
vendor: Object.keys(dependencies),
app: [
"react-hot-loader/patch",
"./js/index.js"
]
},
output: {
path: path.resolve(__dirname, "build"),
filename: "[name]-[hash].js"
},
module: {
rules: [
{
test: /\.jsx?$/,
loader: "babel-loader",
exclude: /node_modules/,
options: {
plugins: [
[
"react-css-modules",
{
context
}
]
]
}
},
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: [
{
loader: "css-loader",
options: {
modules: true,
importLoaders: 1,
localIdentName: "[path]___[name]__[local]___[hash:base64:5]",
sourceMap: true
}
},
'postcss-loader'
]
})
}
]
},
plugins: [
new webpack.optimize.CommonsChunkPlugin({
name: "vendor"
}),
new HtmlWebpackPlugin({
filename: "index.html",
template: "index.html"
}),
new webpack.NamedModulesPlugin(),
new ExtractTextPlugin("css/[name].css")
],
devServer: {
contentBase: path.resolve(__dirname, "src"),
historyApiFallback: true
},
devtool: "eval"
}
index.js
import ReactDOM from "react-dom"
import React from "react"
import {AppContainer} from "react-hot-loader"
import App from "./App.jsx"
const render = Component => {
ReactDOM.render(
<AppContainer>
<Component />
</AppContainer>,
document.getElementById("app")
)
}
render(App)
if (module.hot) {
module.hot.accept("./App.jsx", () => render(App))
}