When I run npm run build I get the following error message.
[copy-webpack-plugin] unable to locate 'path\to\project\public' at 'path\to\project\public'
I moved the public folder to src/main/resources/public. However I can't find a config to change the path. I think the relevant code is in node_modules\#vue\cli-service\lib\config\app.js
// copy static assets in public/
webpackConfig
.plugin('copy')
.use(require('copy-webpack-plugin'), [[{
from: api.resolve('public'),
to: api.resolve(options.outputDir),
ignore: ['index.html', '.DS_Store']
}]])
How do I override this in vue.config.js?
This works for me using vue-cli 3.0. Just add it to your vue.config.js file.
module.exports = {
chainWebpack: config => {
config
.plugin('html')
.tap(args => {
return [{template: '/path/to/index.html'}]
})
}
}
Though this might be more technically correct.
module.exports = {
chainWebpack: config => {
config
.plugin('html')
.tap(args => {
args[0] = {
template: '/path/to/index.html'
}
return args
})
}
}
Edit:
Actually this would be the preferred way of doing this so that none of the other defaults are overwritten.
module.exports = {
chainWebpack: config => {
config
.plugin('html')
.tap(args => {
args[0].template = '/path/to/index.html'
return args
})
}
}
Related
I have this monorepo js setup with yarn workspaces and lerna
/package.json
/packages
/common (js shared code)
/package.json
/mobile (react native - metro)
/package.json
/web (CRA)
/package.json
Mobile and web packages are importing common package inside package.json as follow
"dependencies": {
"common": "*",
}
I had to add noHoist option in root package.json so that mobile native dependencies don't get hoisted so build scripts still run fine
"workspaces": {
"packages": [
"packages/*"
],
"nohoist": [
"**/react-native",
"**/react-native/**"
]
}
Web did work fine before and after adding noHoist option
React native metro bundling start failing after adding noHoist .. it shows
"Error: Unable to resolve module .. could not be found within the project or in these directories:
node_modules
../../node_modules"
However common package does actually exists under root node_modules ?
Looks like some kind of a linking issue ! (did try to link it manually/ same issue) .. note that I didn't add common package under noHoist
here how my metro config looks like
const path= require('path');
const watchFolders = [
path.resolve(`${__dirname}`), // Relative path to package node_modules
path.resolve(`${__dirname}/../../node_modules`), // Relative path to root node_modules ];
module.exports = {
transformer: {
getTransformOptions: async () => ({
transform: {
experimentalImportSupport: false,
inlineRequires: true,
},
}),},
maxWorkers: 2,
watchFolders, };
ANY IDEA ? 🧐
Turns out the issue was in bundling, fixed by editing metro.config.js to include blocklist and extraNodeModules
const path = require('path');
const exclusionList = require('metro-config/src/defaults/exclusionList');
const getWorkspaces = require('get-yarn-workspaces');
function generateAssetsPath(depth, subpath) {
return `/assets`.concat(
Array.from({ length: depth })
// eslint-disable-next-line no-unused-vars
.map((_, i) => `/${subpath}`)
.join(''),
);
}
function getMetroAndroidAssetsResolutionFix(params = {}) {
const { depth = 3 } = params;
let publicPath = generateAssetsPath(depth, 'dir');
const applyMiddleware = (middleware) => (req, res, next) => {
// eslint-disable-next-line no-plusplus
for (let currentDepth = depth; currentDepth >= 0; currentDepth--) {
const pathToReplace = generateAssetsPath(currentDepth, 'dir');
const replacementPath = generateAssetsPath(depth - currentDepth, '..');
if (currentDepth === depth) {
publicPath = pathToReplace;
}
if (req.url.startsWith(pathToReplace)) {
req.url = req.url.replace(pathToReplace, replacementPath);
break;
}
}
return middleware(req, res, next);
};
return {
publicPath,
applyMiddleware,
};
}
function getNohoistedPackages() {
// eslint-disable-next-line global-require
const monorepoRootPackageJson = require('../../package.json');
const nohoistedPackages = monorepoRootPackageJson.workspaces.nohoist
.filter((packageNameGlob) => !packageNameGlob.endsWith('**'))
.map((packageNameGlob) => packageNameGlob.substring(3));
return nohoistedPackages;
}
function getMetroNohoistSettings({
dir,
workspaceName,
reactNativeAlias,
} = {}) {
const nohoistedPackages = getNohoistedPackages();
const blockList = [];
const extraNodeModules = {};
nohoistedPackages.forEach((packageName) => {
extraNodeModules[packageName] =
reactNativeAlias && packageName === 'react-native'
? path.resolve(dir, `./node_modules/${reactNativeAlias}`)
: path.resolve(dir, `./node_modules/${packageName}`);
const regexSafePackageName = packageName.replace('/', '\\/');
blockList.push(
new RegExp(
`^((?!${workspaceName}).)*\\/node_modules\\/${regexSafePackageName}\\/.*$`,
),
);
});
return { extraNodeModules, blockList };
}
const workspaces = getWorkspaces(__dirname);
const androidAssetsResolutionFix = getMetroAndroidAssetsResolutionFix({
depth: 3,
});
const nohoistSettings = getMetroNohoistSettings({
dir: __dirname,
workspaceName: 'mobile',
});
module.exports = {
transformer: {
// Apply the Android assets resolution fix to the public path...
// publicPath: androidAssetsResolutionFix.publicPath,
getTransformOptions: async () => ({
transform: {
experimentalImportSupport: false,
inlineRequires: true,
},
}),
},
// server: {
// // ...and to the server middleware.
// enhanceMiddleware: (middleware) =>
// androidAssetsResolutionFix.applyMiddleware(middleware),
// },
// Add additional Yarn workspace package roots to the module map.
// This allows importing importing from all the project's packages.
watchFolders: [
path.resolve(__dirname, '../../node_modules'),
...workspaces.filter((workspaceDir) => !(workspaceDir === __dirname)),
],
maxWorkers: 2,
resolver: {
// Ensure we resolve nohoisted packages from this directory.
blockList: exclusionList(nohoistSettings.blockList),
extraNodeModules: nohoistSettings.extraNodeModules,
},
};
You can check this universal CRA/RN mono-repo that uses such metro configs
The Metro bundler for react-native cli is unable to resolve a .vrx file (used for a viroreact AR scene).
I've tried to create an rn-cli.config.js file in the project root that should have sorted it but it isn't. What am I missing?
I've tried to create an rn-cli.config.js file in the project root that should have sorted it but it isn't. What am I missing?
The path specified is definitely correct in the requiring .js
rn-cli.config.js
const { getDefaultConfig } = require("metro-config");
module.exports = (async () => {
const {
resolver: { assetExts }
} = await getDefaultConfig();
return {
resolver: {
assetExts: [...assetExts, "obj", "mtl", "JPG", "vrx", "fbx", "hdr"]
}
};
})();
Metro bundler reporting this error
error: bundling failed: Error: Unable to resolve module `./js/res/coffee_mug/object_coffee_mug.vrx` from `C:\Users\Dave\Documents\schoolOfCode\Final Project\final-project-app-brumgo-front-end\components\ARtest\index.js`: The module `./js/res/coffee_mug/object_coffee_mug.vrx` could not be found from `C:\Users\Dave\Documents\schoolOfCode\Final Project\final-project-app-brumgo-front-end\components\ARtest\index.js`. Indeed, none of these files exist:
Please update the metro.config.js at the root of your project as follows.
const {getDefaultConfig} = require('metro-config');
module.exports = (async () => {
const {
resolver: {assetExts},
} = await getDefaultConfig();
return {
resolver: {
assetExts: [
...assetExts,
'obj',
'mtl',
'JPG',
'vrx',
'hdr',
'gltf',
'glb',
'bin',
'arobject',
'gif',
],
},
};
})();
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]
})
}
}
vue.js webpack problem: I can't add a plugin to vue.config.js with configureWebpack
I created a vue.js project with vue cli 3. I am following the example in:
https://cli.vuejs.org/guide/webpack.html
My vue.config.js:
let webpack = require('webpack');
module.exports = {
configureWebpack: {
plugins: [
new webpack.DefinePlugin({
__TEST_MESSAGE__: JSON.stringify('howdy there!')
})
]
},
};
The resolved webpack config looks like:
{
mode: 'production',
...
plugins: [
/* config.plugin('vue-loader') */
new VueLoaderPlugin(),
/* config.plugin('define') */
new DefinePlugin(
{
'process.env': {
VUE_APP_CLI_UI_URL: '""',
NODE_ENV: '"production"',
BASE_URL: '"/"'
}
}
),
/* config.plugin('case-sensitive-paths') */
new CaseSensitivePathsPlugin(),
...
/////////////////////////////////////////////////////
// Inserted note for SO: This is messed up! Should
// be:
// new DefinePlugin({ __TEST_MESSAGE__: '"howdy there!"' })
/////////////////////////////////////////////////////
{
definitions: {
__TEST_MESSAGE__: '"howdy there!"'
}
}
],
...
}
configureWebPack is supposed to merge my plugins with the vue defined plugins. Why is it stripping the DefinePlugin class out and just including the argument to the constructor in the plugins array?
Because Vue already includes the DefinePlugin, you need to modify it using Webpack's chain API instead of attempting to add a new one.
module.exports = {
chainWebpack: config => {
config.plugin('define').tap(args => {
args[0].__TEST_MESSAGE__ = JSON.stringify('howdy there!')
return args
})
}
}
This results in the following config (just an example)...
new DefinePlugin(
{
'process.env': {
NODE_ENV: '"development"',
BASE_URL: '"/"'
},
__TEST_MESSAGE__: '"howdy there!"'
}
),
See https://cli.vuejs.org/guide/webpack.html#modifying-options-of-a-plugin
I am new in using vue to build web app.
By default, use npm run build, it will build the following structure:
But I hope to build as follow:
Then, how can I write the vue.config.js as output like what I want?
Using this GitHub issue as an example, you should be able to achieve this by adding something like this to your configuration...
// vue.config.js
module.exports = {
chainWebpack: config => {
config.module.rule('images').use('url-loader')
.loader('file-loader') // replaces the url-loader
.tap(options => Object.assign(options, {
name: 'images/register/[name].[hash:8].[ext]'
}))
config.module.rule('svg').use('file-loader')
.tap(options => Object.assign(options, {
name: 'images/register/[name].[hash:8].[ext]'
}))
},
css: {
extract: {
filename: 'css/register/[name].[hash:8].css',
chunkFilename: 'css/register/[name].[hash:8].css'
}
},
configureWebpack: {
output: {
filename: 'js/register/[name].[hash:8].js',
chunkFilename: 'js/register/[name].[hash:8].js'
}
}
}
See https://cli.vuejs.org/config/#vue-config-js for more information and examples.