I am relatively new to express + webpack, so i am unclear wether this is intended or not, and if not, how to properly configure it. the question is around the additional asset & entry point created when using the mini-css-extract-plugin.
webpack config:
Extract = require('mini-css-extract-plugin');
path = require('path');
Write = require('write-file-webpack-plugin');
module.exports = {
mode: 'development',
entry: {
demo_scripts: path.resolve('server', 'scripts', 'demo.js'),
demo_styles: path.resolve('server', 'styles', 'demo.css')
},
output: {
path: path.resolve('.tmp'),
filename: '[name].js'
},
plugins: [new Write(), new Extract()],
module: {
rules: [
{
test: /\.js$/,
use: [
{
loader: 'babel-loader',
options: {
presets: ['babel-preset-env']
}
}
]
},
{
test: /\.css/,
use: [
{
loader: Extract.loader
},
{
loader: 'css-loader'
}
]
}
]
}
};
webpack output
Asset Size Chunks Chunk Names
demo_scripts.js 3.91 KiB demo_scripts [emitted] demo_scripts
demo_styles.css 36 bytes demo_styles [emitted] demo_styles
demo_styles.js 3.89 KiB demo_styles [emitted] demo_styles
Entrypoint demo_scripts = demo_scripts.js
Entrypoint demo_styles = demo_styles.css demo_styles.js
my question is, why is demo_styles.js being created? although the css is being extracted, it almost seems like webpack is still creating a bundled js with css, but when i view that file, the only line in it is
eval("// extracted by mini-css-extract-plugin\n\n//# sourceURL=webpack:///./server/styles/demo.css?");
can anyone help explain what is going on here?
UPDATE
if i remove the demo_styles entry point, and configure it via the plugin init, no css asset is built.
({
plugins: [
new Write(),
new Extract({
filename: 'demo_styles.css'
})
]
});
Asset Size Chunks Chunk Names
demo_scripts.js 3.91 KiB demo_scripts [emitted] demo_scripts
Entrypoint demo_scripts = demo_scripts.js
the repo for this is here (note the express branch) https://github.com/brewster1134/bumper/tree/express
There are two workarounds for your problem. For both of them, you need to change the entry point of the Webpack configuration file. I, personally, prefer the first option.
Option 1:
Change the entry to the following:
entry: {
demo: [
path.resolve('server', 'scripts', 'demo.js'),
path.resolve('server', 'styles', 'demo.css'),
]
}
This will generate the following outputs (based on the filename you provided for Extract class and output section:
demo.js
demo_styles.css
Option 2:
For this option, you need to remove the CSS file from the entry point and import it inside the JS file:
webpack.config.js
...
entry: path.resolve('server', 'scripts', 'demo.js'),
...
demo.js
import './../styles.demo.css'
//rest of your JS codes
This solution will generate the same output as Option1
Webpack pulls everything into a js file, then MiniCssExtractPlugin takes it out of that file, leaving a blank js file with // extracted by mini-css-extract-plugin.
My solution is to group your css and js in the entry section of webpack.config.js
entry: {
demo: {
import: [ path.join("server", "scripts", "demo.js"), path.join("server", "styles", "demo.css") ],
filename: "demo.js", // outputs demo.js, demo.css to your output directory
},
main: {
import: [ path.join("server", "scripts", "main.js"), path.join("server", "styles", "main.css") ],
filename: "main.js", // outputs main.js, main.css to your output directory
},
}
Also, so naming works well, use this for your plugins section:
plugins: [
new MiniCssExtractPlugin({
filename: "[name].css"
}),
],
Adjust the bundles "demo" and "main", as well as paths accordingly.
Please remove demo_styles from your entry point this is creating demo_styles.js.
instead you can inject css file like this:
plugins: [
new MiniCssExtractPlugin({
filename: 'demo_styles.css',
}),
Let me know if the issue still persists, Happy to help
Related
I developed a debug extension which uses an external js debugger adapter. I put the js file to the bin directory looks like this.
rootDir
--bin
----adapter.js
And I used it like this in my development environment.
{
"label": "ThingIO Debugger",
"program": "./bin/adapter.js",
"runtime": "node",
"type": "thingio-debug"
}
The code works well in my development mode, but when I packaged it to a .vsix file and install to another machine, it failed immediately.
The webpack file is below
//#ts-check
'use strict';
const path = require('path');
//#ts-check
/** #typedef {import('webpack').Configuration} WebpackConfig **/
/** #type WebpackConfig */
const extensionConfig = {
target: 'node', // vscode extensions run in a Node.js-context ๐ -> https://webpack.js.org/configuration/node/
mode: 'none', // this leaves the source code as close as possible to the original (when packaging we set this to 'production')
entry: './src/extension.ts', // the entry point of this extension, ๐ -> https://webpack.js.org/configuration/entry-context/
output: {
// the bundle is stored in the 'dist' folder (check package.json), ๐ -> https://webpack.js.org/configuration/output/
path: path.resolve(__dirname, 'dist'),
filename: 'extension.js',
libraryTarget: 'commonjs2'
},
externals: {
vscode: 'commonjs vscode' // the vscode-module is created on-the-fly and must be excluded. Add other modules that cannot be webpack'ed, ๐ -> https://webpack.js.org/configuration/externals/
// modules added here also need to be added in the .vscodeignore file
},
resolve: {
// support reading TypeScript and JavaScript files, ๐ -> https://github.com/TypeStrong/ts-loader
extensions: ['.ts', '.js']
},
module: {
rules: [
{
test: /\.ts$/,
exclude: /node_modules/,
use: [
{
loader: 'ts-loader'
}
]
}
]
},
devtool: 'nosources-source-map',
infrastructureLogging: {
level: "log", // enables logging required for problem matchers
},
};
module.exports = [ extensionConfig ];
And the vscode:prepublish command is webpack --mode production --devtool hidden-source-map
I think it looks like the debugger adapter program is not found. So I checked the ~/.vscode/extensions, and the adapter js file exists in the right path.
Now I'm very confused about what wrong is with the extension. Maybe the path is wrong or the webpack did not compile the right file in some situation?
Can anyone give some solution or suggestion about this?
I am trying to set up a PWA for an app in Laravel (5.8) with vuejs (2.5).
This is the configuration I have in mix.js:
...
mix.js('resources/js/app.js', 'public/js')
.generateSW({
// Define runtime caching rules.
runtimeCaching: [{
// Match any request that ends with .png, .jpg, .jpeg or .svg.
urlPattern: /\.(?:png|jpg|jpeg|svg)$/,
// Apply a cache-first strategy.
handler: 'CacheFirst',
options: {
// Use a custom cache name.
cacheName: 'images',
// Only cache 10 images.
expiration: {
maxEntries: 10,
},
},
}],
skipWaiting: true
})
.vue()
.copy('node_modules/lodash/lodash.min.js', 'public/js')
.copy('./resources/manifest.json', 'public/dist/manifest.json')
.copy('./resources/icons', 'public/dist/')
.extract(['vue'])
.webpackConfig({
output: {
filename: '[name].js',
chunkFilename: `[name].chunk.[contenthash:8].js`,
path: path.join(__dirname, 'public/dist'),
publicPath: '/dist/'
},
resolve: {
alias: {
'vue$': 'vue/dist/vue.common.js',
'variables': path.resolve('resources/sass/_variables.scss')
}
},
plugins: [
new webpack.ContextReplacementPlugin(
/moment[\/\\]locale$/,
/(en|es)$/
),
]
})
.options({
processCssUrls: false,
});
...
The service worker was installed correctly and the first time it loads it caches my assets.
But the next calls I make (reload the page) don't use that cache and reload the assets from the network.
However, what I am looking for is a quick initial load after the PWA is installed and this is not happening.
I have done this before with Angular and the PWA module and the assets are loaded from cache, and if there are changes, they are updated later, which makes the initial load of the application very fast.
Can someone help me with this?
In the end I ended up using workbox-cli with this setup:
// workbox.config.js
module.exports = {
"globDirectory": "public/",
"globPatterns": [
"**/*.{js,css,ico,woff2,webmanifest}",
"**/images/icons/*",
"**/images/*",
],
// 15mb max file size
maximumFileSizeToCacheInBytes: 15 * 1024 * 1024,
globIgnores: [
'**/mix-manifest.json',
'**/js/{manifest,vendor}.js',
'**/js/chunks/*',
],
"swDest": "public/service-worker.js",
"swSrc": "resources/sw-offline.js"
};
And running this at the end of my npm run prod
workbox injectManifest workbox.config.js
All credit to this repository:
https://github.com/aleksandertabor/flashcards
So first of all, I have 2 env file,
env.dev
BASE_URL=xxxx
.env
BASE_URL=xxxx
I tried to load BASE_URL from my env file, so I use nuxt/dotenv to load env file on nuxt.config.js, like this,
buildModules: [
'#nuxtjs/eslint-module',
['#nuxtjs/dotenv', { filename: '.env' + process.env.ENV }]
],
modules: [
'#nuxtjs/axios',
'#nuxtjs/auth',
'#nuxtjs/dotenv'
],
axios: {
baseURL: process.env.BASE_URL,
redirectError: {
401: '/login',
403: '/login',
404: '/notfound'
}
}
But when I try to hit API login, it's always pointing to BASE_URL on .env.
What am I do wrong?
Here I wrote a quick answer on how to user env variables: https://stackoverflow.com/a/67705541/8816585
Here is an answer on how to use a specific .env.dev file: https://github.com/nuxt-community/dotenv-module/issues/59#issuecomment-660646526
yarn add -D #nuxtjs/dotenv
In nuxt.config.js
modules: ['#nuxtjs/dotenv'],
...
buildModules: [
['#nuxtjs/dotenv',
{ filename: '.env.' + process.env.ENV }
]
],
In package.json (your probably missed this one)
"scripts": { "dev": "ENV=dev nuxt" }
And finally, do not forget to add them all to your .gitignore file.
Meanwhile, this way of working is not the recommended way as stated in the official dotenv project: https://github.com/motdotla/dotenv#should-i-have-multiple-env-files
I have successfully used the webfonts-loader package to generate a font and class-definitions for icons, but it isn't served by my nuxt dev server. There is a styletag in my head with:
#font-face {
font-family: "TopLoggerIcons";
src: url("/myfont.eot?#iefix") format("embedded-opentype"), url("/myfont.woff2") format("woff2");
}
But the requested http://localhost:3010/myfont.woff2 gives a 404. I had this working in the nuxt version before 2.0 (and before webpack 4), where the file is served from http://localhost:3010/_nuxt/myfont.woff2. The font is currently also served from there, but the path in the font-face declaration is wrong. I'm wondering what has changed here removing the (required?) _nuxt part in the path.
In my nuxt.config.js file I have:
build: {
extend(config, ctx) {
config.module.rules.push({
test: /plugins\/icons\.js$/,
use: ['vue-style-loader', 'css-loader', 'webfonts-loader'],
})
},
}
Now according to the example on the webfonts-loader lib I need to use the MiniCssExtractPlugin.loader instead of the vue-style-loader, but that doesn't work. I read here that it is internally used by nuxt, but i don't know how to add it here.
Hope anyone has an idea where to look...
Ok, just figured it out: you have to use the publicPath option of the webfonts-loader package:
extend(config, ctx) {
config.module.rules.push({
test: /plugins\/icons\.js$/,
use: [
'vue-style-loader',
'css-loader',
{
loader: 'webfonts-loader',
options: {
publicPath: config.output.publicPath,
},
}
],
})
}
The config.output.publicPath is /_nuxt/.
I'm using Webpack (v4), Sass and Vue.js (v2) in my project.
In some cases, I'd like to compile sass code into .css files. (This is for the .scss files that are mentioned in webpack.config.js as "entry" points)
In some other cases I'd like to have the compiled sass code injected into a html tag. (This is for the <style lang="sass"> included in my .vue single file components)
Is it possible to have both at the same time? How should I configure Webpack?
You can use sass-loader to include scss files anywhere and compile them:
https://github.com/webpack-contrib/sass-loader
To include scss in a single-file-component, you don't have to do anything specific, just write your styles into a style tag specifying lang="scss".
Here is a detailed example for both cases:
https://medium.com/hong-kong-tech/use-sass-scss-of-webpack-in-vuejs-8dde3a83611e
You can only leave scss files for webpack to process. You can't get them processed during build time and inject them into your single components, as stated here "In some other cases I'd like to have the compiled sass code injected into a html tag. (This is for the included in my .vue single file components)".
You have to leave to webpack the burden to compile all your scss files into css. Then you choose to either extract them or leave them in the html style tag.
Sorry PlayMa256 & Mรกtรฉ, for being so long before answering your replies.
In the end I found the solution of using two different configurations for my two cases. Webpack allows it through its multi-compiler feature.
So here is what my webpack.config.js now looks like:
module.exports = [ // notice that we are handling an array of configurations here
// In this first config, I manage the first of my use cases:
// Compilation of .scss files into .css files
{
name: "css",
entry: { /* ... */ },
output: { /* ... */ },
/* ... */
module: {
rules: [
{
test: /\.scss$/,
use: [ MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader', 'sass-loader' ],
}
]
},
plugins: [ /* ... */]
},
// In this other config, I manage the other of my use cases:
// injection of the <style> blocks of my .vue files into the DOM
{
name: "main", // name for first configuration
entry: { /* ... */ },
output: { /* ... */ },
/* ... */
module: {
rules: [
// Vue single file components loader
{
test: /\.vue$/,
loader: 'vue-loader',
},
// Injection of <style> elements into the DOM,
// for both plain `.css` files and `<style>` blocks in `.vue` files
{
test: /\.css$/,
use: [
'vue-style-loader',
'css-loader'
]
},
// Compilation of sass code,
// (This actually works both for `.css` files and `<style>` blocks in `.vue` files,
// but I don't have any `.css` as entry for this config.)
{
test: /\.scss$/,
use: [
"style-loader", // creates style nodes from JS strings
"css-loader", // translates CSS into CommonJS
"sass-loader" // compiles Sass to CSS, using Node Sass by default
]
}
]
},
plugins: [ /* ... */]
}
];