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
Related
I have just created a new CRA app. In our organization we have a micro frontend framework which has certain requirements when it comes to the the asset file of each micro frontend app. CRA will by default, create a asset-manifest.json file.
https://github.com/facebook/create-react-app/blob/main/packages/react-scripts/config/webpack.config.js#L656
Now I need to change this file to assets.json and make some structural changes as well. To achieve this I use CRACO and add the WebpackManifestPlugin.
const ManifestPlugin = require('webpack-manifest-plugin');
module.exports = {
webpack: {
plugins: {
// tried removing CRA definition for ManifestPlugin.
// It worked, but had no impact on my problem
// remove: ['ManifestPlugin'],
add: [
new ManifestPlugin({
fileName: 'assets.json',
generate: (seed, files, entrypoints) => {
const js = [],
css = [];
files.forEach((file) => {
if (file.path.endsWith('.js') && file.isInitial) {
js.push({ value: file.path, type: 'entry' });
}
if (file.path.endsWith('.css') && file.isInitial) {
css.push({ value: file.path, type: 'entry' });
}
});
return { js, css };
},
})
]
}
}
};
Whenever I build the application, my new assets.json file is generated as expected.
However, I can't get CRA, or webpack-dev-server I assume, to serve this file while I run my CRA app in development mode. It only resolves to the index.html file. I have looked through CRA source code and can't really find any relevant place where asset-manifest.json is mentioned.
So how do I get webpack-dev-server to serve my assets.json file?
You need to add the ManifestPlugin to webpack.plugins.remove array to receive only the configuration from WebpackManifestPlugin:
...
webpack: {
alias: {},
plugins: {
add: [
new WebpackManifestPlugin(webpackManifestConfig)
],
remove: [
"ManifestPlugin"
],
},
configure: (webpackConfig, { env, paths }) => { return webpackConfig; }
},
...
I am working on creating an Outlook addin project following the below tutorial:-
https://learn.microsoft.com/en-us/office/dev/add-ins/quickstarts/outlook-quickstart?tabs=yeomangenerator
During development i added some extra JavaScript files(like helper.js, settings.js) which contains some common and helper functions which are work fine while running locally,
Now when i run "npm run build" command for generating a published version of the project to be deployed on server these files are missing and thus published project is not working due to missing functions.
Below is my project.
project structure
missing helper and setting folder
below is my webpack.config.js boiler plate code
module.exports = async (env, options) => {
const dev = options.mode === "development";
const buildType = dev ? "dev" : "prod";
const config = {
devtool: "source-map",
entry: {
polyfill: ["core-js/stable", "regenerator-runtime/runtime"],
taskpane: "./src/taskpane/taskpane.js",
commands: "./src/commands/commands.js",
landing: "./src/landing/landing.js"
},
resolve: {
extensions: [".html", ".js"]
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: ["#babel/preset-env"]
}
}
},
{
test: /\.html$/,
exclude: /node_modules/,
use: "html-loader"
},
{
test: /\.(png|jpg|jpeg|gif)$/,
loader: "file-loader",
options: {
name: '[path][name].[ext]',
}
}
]
},
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
filename: "taskpane.html",
template: "./src/taskpane/taskpane.html",
chunks: ["polyfill", "taskpane"]
}),
new CopyWebpackPlugin({
patterns: [
{
to: "taskpane.css",
from: "./src/taskpane/taskpane.css"
},
{
to: "[name]." + buildType + ".[ext]",
from: "manifest*.xml",
transform(content) {
if (dev) {
return content;
} else {
return content.toString().replace(new RegExp(urlDev, "g"), urlProd);
}
}
}
]}),
new HtmlWebpackPlugin({
filename: "commands.html",
template: "./src/commands/commands.html",
chunks: ["polyfill", "commands"]
}),
new HtmlWebpackPlugin({
filename: "landing.html",
template: "./src/landing/landing.html",
chunks: ["polyfill", "dialog"]
})
],
devServer: {
headers: {
"Access-Control-Allow-Origin": "*"
},
https: (options.https !== undefined) ? options.https : await devCerts.getHttpsServerOptions(),
port: process.env.npm_package_config_dev_server_port || 3000
}
};
return config;
};
Could you please help
Finally found the solution, We need to include the custom/helper js files by
marking the functions as export & making them require on the main files that needs &
then use the functions exported and
once we run "npm run build" function is available as the part of main file which made it required
below is the example of the same
//custom or helper file in a subfodler
sample.js
export function sampleFunc() {
//some codeenter code here
}
taskpane.js // main file where we need to use
const samJs = require("./../helpers/sample"); // without extesion
//Call the function
var data = samJs.sampleFunc
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.
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.
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]
})
}
}