how to use exclude with babel-loader in vue cli3? - vue.js

I want to use exclude to ignore some dir to not compile, but in Vue Cli3, it not works. My option is:
chainWebpack: config => {
config.module
.rule('js')
.test(/\.jsx?$/)
.use('babel-loader')
.loader('babel-loader')
.exclude
.add(resolve('src/libs/iview')) // this line not work
.end();
}
Error:
TypeError: Cannot read property 'add' of undefined

To exclude a file from Babel transpile, you can use the excludes option for the js babel-loader. An example is below.
Caveats:
Strings must be absolute paths (use path.resolve if needed)
Regexp works
Functions work
// const path = require('path') // somewhere at the top of the file...
chainWebpack: config => {
config.module
.rule('js')
.exclude
.add(/path\/to\/folder\/.+\.ignore/) // Regexp: ignore anything inside of path/to/folder that has .ignore in the file extension
// .add(path.resolve('./path/to/the/folder')) // example with a nix folder
// .add('C:\\path\\to\\the\\folder\\') // absolute path, example with a Windows folder
.end()
}
The command vue inspect module.rules will return:
[...]
/* config.module.rule('js') */
{
test: /\.m?jsx?$/,
exclude: [
function () { /* omitted long function */ },
'C:\\path\\to\\the\\folder\\'
],
use: [
/* config.module.rule('js').use('cache-loader') */
{
loader: 'cache-loader',
options: {
cacheDirectory: '[...]\\node_modules\\.cache\\babel-loader',
cacheIdentifier: '2e75750d'
}
},
/* config.module.rule('js').use('babel-loader') */
{
loader: 'babel-loader'
}
]
}

Just remove this:
.use('babel-loader')
.loader('babel-loader')
and it works.

Related

Vue Storybook doesn't compile with Pug components

I am trying to add storybook to my project, which written using pug. Unfortunately, storybook stops to compile if I create story with component on pug. If I change template lang to html (and template itself), all works just fine.
I had this same issue last night when adding storybook to an existing Vue/Pug project.
Storybook supports extending it's webpack config.
First open the file .storybook/main.js in your project directory.
Here you can add a function for webpackFinal to the object, which received the webpack config as an argument, and u can push additional loaders into the rules.
More info here in the storybook docs:
https://storybook.js.org/docs/vue/configure/webpack
Here is my file where i have added pug and sass support:
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 }) => {
// `configType` has a value of 'DEVELOPMENT' or 'PRODUCTION'
// You can change the configuration based on that.
// 'PRODUCTION' is used when building the static version of storybook.
// Make whatever fine-grained changes you need
config.module.rules.push({
test: /\.scss$/,
use: ['style-loader', 'css-loader', 'sass-loader'],
include: path.resolve(__dirname, '../'),
});
config.module.rules.push(
{
test: /\.pug$/,
use: [
{ loader: 'pug-plain-loader' }
]
}
);
// Return the altered config
return config;
},
}

vue.config.js & webpack 4: override 'exclude' or 'include' of rule

I want to override the exclude / include of a webpack rule. The project has been created with vue-cli-sevice and therefore only has a vue.config.js. I am able to hook into the configuration with chainWebpack, but I'm not able to edit the rule itself.
The output of vue-cli-service inspect contains the rule I want to edit:
/* config.module.rule('js') */
{
test: /\.jsx?$/,
exclude: [
function () { /* omitted long function */ }
],
use: [
{
loader: 'cache-loader',
options: {
cacheDirectory: '/Users/m/projects/echo/.../.cache/babel-loader',
cacheIdentifier: '4b5cee3d'
}
},
{
loader: 'babel-loader'
}
]
},
I now want to edit this configuration from my vue.config.js (the commented out part shows how I found it in the documentation but it's not working):
const chainWebpack = (config) => {
config.module.rule('js');
// .include
// .add('node-modules/blubb')
// .end();
};
module.exports = {
chainWebpack
};
How can I add an include or override the exclude property of this rule configuration?
I got it working like so. This clears the whole exclude and adds an include.
const chainWebpack = (config) => {
config.module
.rule('js')
.test(/\.jsx?$/)
.exclude
.clear()
.end()
.include
.add(function() {
return [
'node_modules/include-me',
'src'
]
})
.end()
};
The easiest way to check if everything works as expected is IMO to run vue-cli-service inspect. Change the config, check if inspect fails and, if it doesn't, check if the output contains the desired changes.
/* config.module.rule('js') */
{
test: /\.m?jsx?$/,
exclude: [
filepath => {
// always transpile js in vue files
if (/\.vue\.jsx?$/.test(filepath)) {
return false
}
// exclude dynamic entries from cli-service
if (filepath.startsWith(cliServicePath)) {
return true
}
// only include #babel/runtime when the #vue/babel-preset-app preset is used
if (
process.env.VUE_CLI_TRANSPILE_BABEL_RUNTIME &&
filepath.includes(path.join('#babel', 'runtime'))
) {
return false
}
// check if this is something the user explicitly wants to transpile
if (transpileDepRegex && transpileDepRegex.test(filepath)) {
return false
}
// Don't transpile node_modules
return /node_modules/.test(filepath)
}
],
use: [
{
loader: '/Users/penglz/codeLab/mantis/node_modules/cache-loader/dist/cjs.js',
options: {
cacheDirectory: '/Users/penglz/codeLab/mantis/node_modules/.cache/babel-loader',
cacheIdentifier: '12a9bd26'
}
},
{
loader: '/Users/penglz/codeLab/mantis/node_modules/thread-loader/dist/cjs.js'
},
{
loader: '/Users/penglz/codeLab/mantis/node_modules/babel-loader/lib/index.js'
}
]
},
this is full view of vue-cli config, and i can't figure out what will happen after clearing the raw config(code above, exclude: [ filpath => { // some logic }]), so i didn't modify it(like the another answer).
in order to transpile some pkg, i create a new rule in my vue.config.js, it works with raw config
config.module
.rule('resolveNodeModules')
.test(/\.m?jsx?$/)
.include.add(/node_modules\/(vue2-editor|quill|quill-delta)\/.*/)
.end()
.use('babel-loader')
.loader('babel-loader')
in my config, i want to transiple vue2-editor/quill/quill-delta, it works and it should haven't affect raw config

Is there a way to disable filenameHashing only for specific resources (images) in webpack?

After building my website with Vue.js 2.6.2 using vue-cli, I encountered a problem with static resources (images in this case). Webpack bundles them up in the /img/ folder which is fine, but the images are given hashes like image_demo.25d62d92.png which is causing issues when trying to access those resources from an external source e.g. from another website.
There is an option for webpack to disable filenameHashing altogether, but that too great a sacrifice to not have the cache control for all the orher images on the website.
The desired solution is the option to have only some hand picked resources with their default names without the extra hash, while the other resources get the default hash for cache control.
Yes, there is a way. You will need to override the 'images' rule that vue-cli comes with.
vue inspect --rule images yields the following:
$ vue inspect --rule images
/* config.module.rule('images') */
{
test: /\.(png|jpe?g|gif|webp)(\?.*)?$/,
use: [
{
loader: 'url-loader',
options: {
limit: 4096,
fallback: {
loader: 'file-loader',
options: {
name: 'img/[name].[hash:8].[ext]'
}
}
}
}
]
}
(Protip: vue inspect is a useful tool for figuring out why things behave like they do when building with vue-cli)
All images
vue-cli recommends webpack-chain for 'advanced' configuration. I'm personally not a fan, but if you want to remove hashes for all images, you should probably modify the 'images' rule. Edit vue.config.js like so:
module.exports = {
// ...
chainWebpack: (config) => {
config.module
.rule("images")
.use("url-loader")
.loader("url-loader")
.tap((options) => {
options.fallback.options.name = "img/[name].[ext]"
return options
})
}
// ...
}
Specific images
In my case I wanted to remove hashes only for a specific group of images with a unique prefix, so I added the following to configureWebpack in vue.config.js:
module.exports = {
// ...
configureWebpack: {
module: {
rules: [
{
test: /unique-prefix-\d*\.png/, // <= modify this to suit your needs
use: [
{
loader: "url-loader",
options: {
limit: 4096,
fallback: {
loader: "file-loader",
options: {
name: "img/[name].[ext]", // <= note how the hash is removed
},
},
},
},
],
},
],
},
// ...
}
It could probably be done with webpack-chain as well, but I prefer the more vanilla Webpack config format.

How do I exclude a file (eg config file) in Vue.js?

https://cli.vuejs.org/config/#configurewebpack
https://cli.vuejs.org/config/#chainwebpack
I've tried:
chainWebpack: config => {
config.merge({
module: {
rules: [{
test: /\.jsx?$/,
exclude: {
exclude: [path.resolve(__dirname, "public/my-config.js")]
}
}]
}
})
}
Or
config.module.rule('js')
.exclude({
exclude: path.resolve(__dirname, "public/my-config.js")
})
But it doesn't work.
I want to either import public/my-config.js with script tag in the pages/index.html or just import { config1, config2 } from '../public/my-config'.
I was able to use externals to not include a module in webpack though, but it's not quite intuitive with Vue.js.
I must have the my-config.js be available at dist/ so that it can be edited.
Refer to:
https://github.com/neutrinojs/webpack-chain#config-plugins-modify-arguments
https://github.com/webpack-contrib/copy-webpack-plugin#ignore
What I wrote in my vue.config.js:
const path = require("path");
module.exports = {
baseUrl: ".",
chainWebpack: config => {
config.plugin('copy').tap((args) => [[
{
from: '/path/to/my_project/public',
to: '/path/to/my_project/dist',
toType: 'dir',
ignore: [
'index.html',
'.DS_Store',
'config.data.js'
]
}
]]
);
}
}
I used $ vue inspect > output.js then examined the output.js file for what arguments were used for the config.plugin('copy') which happens to be an instance of new CopyWebpackPlugin.
Reference: https://github.com/vuejs/vue-cli/issues/2231#issuecomment-413441633
Try this, much simpler:
module.exports = {
chainWebpack: config => {
config.plugin('copy').tap(([options]) => {
options[0].ignore.push('api/**/*')
return [options]
})
}
}

Why are my js files being loaded as `index.html` instead of the actual js files created by webpack?

I'm creating a simple build from webpack, using typescript, jade, and stylus. When the final index.html file is spit out, however, it seems to think the js files are just the index.html file and not the actual js files bundled up by webpack and dynamically inserted at the bottom of the html body.
My project directory structure looks like this:
- dist (compiled/transpiled files)
- server
- dependencies
- index.js
- app.js
- app.[hash].js
- polyfills.[hash].js
- node_modules
- src
- server
- dependencies
- index.ts
- app.ts
- client (ng2 ts files)
- index.jade
This is my webpack build:
'use strict';
const webpack = require('webpack');
const path = require('path');
const HTMLWebpackPlugin = require('html-webpack-plugin');
const WebpackShellPlugin = require('webpack-shell-plugin');
const rootDir = __dirname;
/**
* Resolve paths so that we don't have to use relative paths when importing dependencies.
* Very helpful when scaling an application and changing the location of a file that my require another file
* in the same directory as the one it used to be in
*/
const pathResolves = [path.resolve(rootDir, 'src'), path.resolve(rootDir, 'node_modules')];
console.log('path', path.resolve(rootDir, 'src/server'));
module.exports = {
entry: {
'app': path.resolve(rootDir, 'src/client/main.ts'),
'polyfills': [
'core-js/es6',
'core-js/es7/reflect',
'zone.js/dist/zone'
]
},
output: {
path: path.resolve(rootDir, 'dist'),
filename: '[name].[hash].js'
},
module: {
rules: [
{
test: /\.component.ts$/,
use: [
{
loader: 'angular2-template-loader'
},
{
loader: 'ts-loader',
options: {
configFileName: path.resolve(rootDir, 'tsconfig.client.json')
}
}],
include: [path.resolve(rootDir, 'src/client')]
},
{
test: /\.ts$/,
use: [
{
loader: 'ts-loader',
options: {
configFileName: path.resolve(rootDir, 'tsconfig.client.json')
}
}
],
exclude: /\.component.ts$/
},
{
test: /\.jade$/,
use: ['pug-ng-html-loader']
},
{
test: /\.styl$/,
use: [
{ loader: 'raw-loader' },
{ loader: 'stylus-loader' }
]
}
]
},
resolve: {
extensions: ['.js', '.ts', '.jade', '.styl'],
modules: pathResolves
},
plugins: [
new webpack.optimize.CommonsChunkPlugin({
name: 'polyfills'
}),
new HTMLWebpackPlugin({
template: path.resolve(rootDir, 'dist/index.html')
}),
/**
* Define any environment variables for client
*/
new webpack.DefinePlugin({
APP_ENV: JSON.stringify(process.env.APP_ENVIRONMENT || 'development')
}),
/**
* This plugin is required because webpack 2.0 has some issues compiling angular 2.
* The angular CLI team implemented this quick regexp fix to get around compilation errors
*/
new webpack.ContextReplacementPlugin(
/angular(\\|\/)core(\\|\/)(esm(\\|\/)src|src)(\\|\/)linker/,
'./'
)
]
};
And finally, this is the src/server/app.ts file that serves up index.html:
import * as express from 'express';
import * as fs from 'fs';
import * as morgan from 'morgan';
import {
Config
}
from './dependencies/config';
export
function app(Container) {
const app = express();
const config: Config = Container.get(Config);
if (config.log.dev) {
app.use(morgan('combined'));
}
app.get('/', (req: express.Request, res: express.Response) => {
const indexPath: string = `dist/index.html`;
const encodeType: string = `utf-8`;
const html = fs.readFile(indexPath, encodeType, (err: Error, result: string) => {
if (err) {
return res.status(500).json(err);
}
return res.send(result);
});
});
return app;
}
The browser console shows the following 404 error messages (they're red in the browser console) when i go to localhost:3000:
GET http://localhost:3000/polyfills.9dcbd04127bb957ccf5e.js
GET http://localhost:3000/app.9dcbd04127bb957ccf5e.js
I know it's supposed to be getting the js files from dist/[file].[hash].js, but can't seem to make it work with webpack. Also, I should note that I set NODE_PATH to ./ in my gulp nodemon config. Any ideas why this isn't working?
Figured it out on my own. Forgot to add app.use(express.static('dist')) middleware to the app.ts file.