How do I exclude a file (eg config file) in Vue.js? - 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]
})
}
}

Related

Express.js Send Files with Hashed File Names Compiled in Webpack

This seemed pretty straightforward but I've searched a while and haven't found any solutions. If there's a better way to set this up, I'm open to suggestions.
When I change code in index.html in the below folder structure and compile with Webpack (which outputs with a new hash in filename), how do I write my Express.js route so that I don't have to change the filename everytime I compile with Webpack? Here's my setup:
Folder Structure:
root/
-dist/
--- index.1de575730aa45442d6bc.html
-src/
--- index.html
--- index.js
-webpack.static.config.js
-server/
--- server.js
Express Route:
app.get('/', (req, res) => {
res.sendFile(/*dynamically send index.[hash].html here*/);
});
webpack.static.config.js
if(process.cwd() !== __dirname) process.chdir(__dirname);
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const dotenv = require('dotenv');
const env = dotenv.config().parsed;
const definition = Object.keys(env).reduce((variables, key, i) => {
variables[key] = JSON.stringify(env[key]);
return def;
}, {});
const minify = {
collapseWhitespace: true,
keepClosingSlash: true,
removeComments: true,
removeRedundantAttributes: true,
removeScriptTypeAttributes: true,
removeStyleLinkTypeAttributes: true,
useShortDoctype: true
};
module.exports = {
module: {
rules: [
{ test: /\.html$/i, use: 'html-loader' },
{ test: /\.js$/i, use: 'babel-loader' },
{ test: /\.css$/i, use: ['style-loader', 'css-loader'] },
{ test: /\.(csv|tsv)$/i, use: ['csv-loader'] },
{ test: /\.xml$/i, use: ['xml-loader'] },
{ test: /\.(png|jpg|jpeg|svg|gif)$/i, type: 'asset/resource', generator: {filename: 'img/[name].[hash][ext][query]'} },
{ test: /\.(woff|woff2|eot|ttf|otf)$/i, type: 'asset/resource', generator: {filename: 'fonts/[name].[hash][ext][query]'} }
]
},
entry: {
home: './src/index.js'
},
output: {
filename: '[name].[hash].bundle.js',
path: path.resolve(__dirname, 'dist')
},
plugins: [
new webpack.optimize.ModuleConcatenationPlugin(),
new webpack.HotModuleReplacementPlugin(),
new webpack.DefinePlugin(definition),
new HtmlWebpackPlugin({ minify, template: path.resolve('./src/index.html'), filename: 'index.[hash].html', chunks: ['home'] })
]
};
Don't know is it still relevant, but I had the same problem recently.
Solved it with readdir method built in Node.js File System Module:
Require file system module and path module:
const path = require('path')
const fs = require('fs')
Change path to folder, where your "html" file is placed:
const pathName = path.resolve(__dirname, '../client/dist')
app.get('/', (req, res) => {
fs.readdir(pathName, (err, files) => {
if (err) {
console.error(err)
return res.status(500)
}
const filename = files.find(file => path.extname(file) === '.html')
res.sendFile(path.resolve(__dirname, '../client/dist', filename))
})
})
fs.readdir method returns array of all files in given directory, so you have to get one with ".html" extension. path.extname is method from Path Module that returns the extension of a file path.
It worked for me, but maybe there is more elegant solution.
P.S.: Or you could just remove "[hash]" from "filename" option in HtmlWebpackPlugin in webpack.static.config.js file.

Webpack compilation error with Cypress-webpack-preprocessor

I am not able to run cypress test and getting foll error:
When I ran cypress run:
It is giving below Webpack compilation error
Webpack Compilation Error
./cypress/integration/features/Pagination.feature
Module not found: Error: Can't resolve
'C:UsersCypressProjectode_modulescypress-cucumber-preprocessorlibesolveStepDefinition' in 'C:\Users\CypressProject\cypress\integration\features'
Somehow backslashes are also not included in above path
My webpack config file is as :
module.exports = {
resolve: {
extensions: [".ts", ".js"]
},
node: { fs: "empty", child_process: "empty", readline: "empty" },
module: {
rules: [
{
test: /\.ts$/,
exclude: [/node_modules/],
use: [
{
loader: "ts-loader"
}
]
},
{
test: /\.feature$/,
use: [
{
loader: "cypress-cucumber-preprocessor/loader"
}
]
}
]
}
};
My plugin file:
const wp = require('#cypress/webpack-preprocessor')
const fs = require('fs-extra')
const path = require('path')
function getConfigurationByFile (file) {
const pathToConfigFile = path.resolve('./cypress/', 'config', `${file}.json`)
return fs.readJson(pathToConfigFile)
}
module.exports = (on,config) => {
const file = process.env.ENV_FILE//config.env.envFile
const options = {
webpackOptions: require("../webpack.config.js")
};
on('file:preprocessor', wp(options))
if(file==null){
return getConfigurationByFile('local');
}
else{
return getConfigurationByFile(file);
}
}
Anybody having idea to resolve?
You should set your step_definition path inside package.json with
"cypress-cucumber-preprocessor": {
"step_definitions": "path/to/steps_definition"
}

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

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

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.

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.