I'm generating documentation for a VueJS component using vue-styleguidist.
This normally works just fine, but in this case I get an error:
./node_modules/vue-awesome/components/Icon.vue
Module parse failed: Unexpected token (1:0)
You may need an appropriate loader to handle this file type.
<template>
<svg version="1.1"
:class="klass"
Learn how to add webpack loaders to your style guide:
https://github.com/vue-styleguidist/vue-styleguidist/blob/master/docs/Webpack.md
My config file for vue-styleguidist (styleguide.config.js) includes the default rules for loading webpack files:
const loaders = require('vue-webpack-loaders');
module.exports = {
...
webpackConfig: {
module: {
loaders,
},
...
},
...
};
Other .vue files are loaded correctly, but not Icon.vue.
The problem is that the default webpack loading rule provided by vue-webpack-loaders specifically excludes mode_modules directory, but the npm module contains that Vue file Icon.vue.
{
test: /\.vue$/,
exclude: /node_modules/,
loader: 'vue-loader',
options: vueLoaderConfig
},
The solution is to add an extra rule to the default rules to specifically load that file under node_modules.
const loaders = require('vue-webpack-loaders');
var vueLoaderConfig = require('vue-webpack-loaders/lib/vue-loader.conf')
loaders.push({
test: /vue-awesome\/components\/Icon\.vue$/, <-- path to .vue file
loader: 'vue-loader',
options: vueLoaderConfig
})
Related
I have a project which I am breaking into multiple workspaces using npm7.
I am using sass in vue components in a package (another workspace), and importing that package into my current workspace.
When I use sass in the workspace in which storybook is running, it compiles fine.
When I use css in the other workspace it compiles fine.
When I use sass in another workspace, it doesn't find the loaders.
ModuleParseError: Module parse failed: Unexpected character '#' (39:0)
File was processed with these loaders:
* ../node_modules/vue-docgen-loader/lib/index.js
* ../node_modules/vue-docgen-loader/lib/index.js
* ../node_modules/vue-loader/lib/index.js
You may need an additional loader to handle the result of these loaders.
|
|
> #import '../../../bootstrap4/scss/functions';
| #import '../../../bootstrap4/scss/variables';
|
at handleParseError (/srv/insight_lerna/submodules/insight_core/insight-javascript/node_modules/webpack/lib/NormalModule.js:469:19)
at /srv/insight_lerna/submodules/insight_core/insight-javascript/node_modules/webpack/lib/NormalModule.js:503:5
at /srv/insight_lerna/submodules/insight_core/insight-javascript/node_modules/webpack/lib/NormalModule.js:358:12
at /srv/insight_lerna/submodules/insight_core/insight-javascript/node_modules/loader-runner/lib/LoaderRunner.js:373:3
at iterateNormalLoaders (/srv/insight_lerna/submodules/insight_core/insight-javascript/node_modules/loader-runner/lib/LoaderRunner.js:214:10)
at iterateNormalLoaders (/srv/insight_lerna/submodules/insight_core/insight-javascript/node_modules/loader-runner/lib/LoaderRunner.js:221:10)
at /srv/insight_lerna/submodules/insight_core/insight-javascript/node_modules/loader-runner/lib/LoaderRunner.js:236:3
at context.callback (/srv/insight_lerna/submodules/insight_core/insight-javascript/node_modules/loader-runner/lib/LoaderRunner.js:111:13)
at Object.module.exports (/srv/insight_lerna/submodules/insight_core/insight-javascript/node_modules/vue-docgen-loader/lib/index.js:28:5)
at LOADER_EXECUTION (/srv/insight_lerna/submodules/insight_core/insight-javascript/node_modules/loader-runner/lib/LoaderRunner.js:119:14)
at runSyncOrAsync (/srv/insight_lerna/submodules/insight_core/insight-javascript/node_modules/loader-runner/lib/LoaderRunner.js:120:4)
at iterateNormalLoaders (/srv/insight_lerna/submodules/insight_core/insight-javascript/node_modules/loader-runner/lib/LoaderRunner.js:232:2)
at iterateNormalLoaders (/srv/insight_lerna/submodules/insight_core/insight-javascript/node_modules/loader-runner/lib/LoaderRunner.js:221:10)
at /srv/insight_lerna/submodules/insight_core/insight-javascript/node_modules/loader-runner/lib/LoaderRunner.js:236:3
at context.callback (/srv/insight_lerna/submodules/insight_core/insight-javascript/node_modules/loader-runner/lib/LoaderRunner.js:111:13)
at Object.module.exports (/srv/insight_lerna/submodules/insight_core/insight-javascript/node_modules/vue-docgen-loader/lib/index.js:28:5)
My main.js works for local sass. It is as follows:
const path = require('path');
module.exports = {
"stories": [
"../src/**/*.stories.mdx",
"../src/**/*.stories.#(js|jsx|ts|tsx)"
],
"addons": [
"#storybook/addon-links",
"#storybook/addon-essentials"
],
"webpackFinal": async (config, { configType }) => {
config.module.rules.push({
test: /\.scss$/,
use: ['style-loader', 'css-loader', 'sass-loader'],
include: path.resolve(__dirname, '../'),
});
// Return the altered config
return config;
},
}
Is it possible to use storybook with npm workspaces?
I am using storybook 6.2.8.
I am using vue.js 2.6.12
On further investigation, I found the error is in the line:
include: path.resolve(__dirname, '../'),
I removed this line and it worked fine. Clearly it is limiting the rule to the current workspace instead of all workspaces.
I've been building my Vue application by using Vue Cli 3.
If I need to import an index.js which is in directory named Dir1, I can import it using
import file1 from '#/components/Dir1/
but somehow it doesn't work with .vue extension files.
I have to expicitly mention the file name such as import Title from #/components/Title/index.vue.
What changes do I have to make in the settings in order to import the .vue extension file without mentioning the filename?
This is how I would do it with Vue.
You may need to tweak the config a little bit to suit your dev environment needs.
Note that this is not a full config but a guideline on what should be done based on NPM directory-named-webpack-plugin documentation.
In your webpack.config.js you should have the following (Webpack 3):
const DirectoryNamedWebpackPlugin = require('directory-named-webpack-plugin');
// ...
let config = {
// ...
module: {
rules: [
{
test: /\.(js|vue)$/,
exclude: /node_modules/,
use: 'babel-loader'
}
]
},
resolve: {
modules: ['components', 'node_modules'],
extensions: ['.js', '.vue'],
plugins: [
new DirectoryNamedWebpackPlugin(true)
]
}
// ...
}
modules.exports = config;
taken and modified for Vue from: Recursive import of components using webpack in React
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: [ /* ... */]
}
];
I am getting the following error when I am trying to run "gulp" in my vue.js project after I have added an image tag in my Home.vue component [ <img class="img-fluid" src="../images/logoWhite.png"> ] :
stream.js:74
throw er; // Unhandled stream error in pipe.
^
Error: ModuleParseError: Module parse failed: G:\Projects\Cakes\src\images\logoWhite.png Unexpected character '�' (1:0)
You may need an appropriate loader to handle this file type.
SyntaxError: Unexpected character '�' (1:0)
I read that this error might be caused by babel and how it is configured in webpack.config.js. After trying some solutions listed, I still haven't managed to get it work. I have also tried to create a '.babelrc' file with the presets conditions for babel, but still it didn't work.
This is how 'webpack.config.js' file looks like:
var webpack = require('webpack')
module.exports = {
entry: [
'./src/main.js'
],
output: {
path: "/dist/js",
publicPath: "/dist/",
filename: "app.js"
},
watch: true,
module: {
loaders: [
{
test: /\.js$/,
// excluding some local linked packages.
// for normal use cases only node_modules is needed.
exclude: /node_modules|vue\/src|vue-router\//,
loader: 'babel'
},
{
test: /\.scss$/,
loaders: ['style', 'css', 'sass']
},
{
test: /\.vue$/,
loader: 'vue'
}
]
},
babel: {
presets: ['es2015'],
plugins: ['transform-runtime']
},
resolve: {
modulesDirectories: ['node_modules']
}
}
In package.json, I have the following packages as my devDependencies for babel:
"babel-core": "^6.1.21",
"babel-loader": "^6.1.0",
"babel-plugin-transform-runtime": "^6.1.18",
"babel-preset-es2015": "^6.13.2",
"babel-runtime": "^6.3.13"
Thanks in advance guys!
I had the same problem and my solution was to use 'file-loader'
Install:
npm install --save-dev file-loader
Add the module rule to your webpack.config.js
{ test: /\.(png|jpg|gif)$/, loader: 'file-loader?name=./images/[name].[ext]' }
CSS file:
.content {
background-image: url('./images/background.jpg');
}
The template section of a .vue file is loaded using vue-html-loader, which will attempt to load local resources (such as image tag src values) using require(<resource>)(details).
The error above is due to the fact that you don't have a webpack loader setup to handle .png files, to fix it you'd need to install and configure a suitable loader - something like this, with url-loader, should work:
{ test: /\.png$/, loader: "url-loader?mimetype=image/png" }
I use some npm packages in my project. Two of them have the wrong main-field. Is it possible to override them?
I use webpack. I found a solution here.
This works for the main field but I also need a css-file from the same package. I refer it with ~package/css/style.css in my index.scss file. With the solution above it resolves the path with path/to/main.js/css/style.css (with main.js) instead of path/to/css/style.css (without main.js).
I could refer it directly ../node_modules/path/to/css/style.css but I think thats ugly.
So is there an other solution with webpack or npm to override this main field?
-- EDIT --
I use bootstrap-treeview as package. I refer it in index.scss like so
#import '~bootstrap-treeview/src/css/bootstrap-treeview.css';. This works.
When I add 'bootstrap-treeview': path.join(_path, 'node_modules', 'bootstrap-treeview', 'src', 'js', 'bootstrap-treeview.js') as alias in webpack import 'bootstrap-treeview'; works but the css not (as describes above).
-- EDIT 2 --
webpack.conf.js:
resolve: {
extensions: ['', '.js'],
modulesDirectories: ['node_modules'],
alias: {
// bootstrap-treeview alias
'bootstrap-treeview': path.join(_path, 'node_modules', 'bootstrap-treeview', 'src', 'js', 'bootstrap-treeview.js')
}
},
module: {
loaders: [
{
test: /\.css$/,
loaders: [
'style-loader',
'css-loader?sourceMap',
'postcss-loader'
]
},
{
test: /\.(scss|sass)$/,
loader: 'style-loader!css-loader?sourceMap!postcss-loader!sass-loader?outputStyle=expanded&sourceMap=true&sourceMapContents=true
}
]
}
index.scss see above.
Error with bootstrap-treeview alias:
Module not found: Error: Cannot resolve 'file' or 'directory' /home/ekf/develop/generator-angular-webpack/node_modules/bootstrap-treeview/src/js/bootstrap-treeview.js/src/css/bootstrap-treeview.css in ...
Error without alias:
Module not found: Error: Cannot resolve module 'bootstrap-treeview' in ...
just in case
webpack scss loader config
module: {
loaders: [
{
test: /\.css$/,
exclude: /node_modules/,
loader: "style-loader!css-loader"
},
{
test: /\.scss$/,
exclude: /node_modules/,
loader: "style-loader!css-loader!sass-loader"
}
]
}
The problem is that your alias points directly to the JS file, instead of pointing to the common ancestor of both the JS and the CSS. It's nice and convenient to be able to import Treeview from "bootstrap-treeview" but it leads to the problem you're describing.
Instead, you could specify a higher level alias:
resolve: {
alias: {
// bootstrap-treeview alias
'bootstrap-treeview': path.join(_path, 'node_modules', 'bootstrap-treeview', 'src')
}
},
and get the JS as import Treeview from "boostrap-treeview/js/bootstrap-treeview.js". This allows you to get the CSS as require("bootstrap-treeview/css/bootstrap-treeview.css").
You might be able to get clever about it and tell Webpack to look for CSS files in ~/css/ and JS files in ~/js/ but that would be adding more magic for (IMHO) little gain.