Hello I am using VueJS and the webpack template. I have a bunch of components I can easily display with Vue Router. However, my organization uses Robot Framework for testing and we generate an HTML page using the command:
python -m robot.testdoc /tests/directory /destination.html
This is basically how I am using the router:
import Vue from 'vue'
import Router from 'vue-router'
import Main from '#/components/Main.vue'
import Component1 from '#/components/Component1.vue'
import Component2 from '#/components/Component2.vue'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
mode: history,
name: 'Main',
component: Main
},
{
path: '/component1',
mode: history,
name: 'Component1',
component: Component1
},
{
path: '/component2',
mode: history,
name: 'Component2',
component: Component2
}
]
})
Is there a way to route to an HTML file using Vue Router?
First you'll need html-loader:
yarn add html-loader | npm install html-loader
Then you need to update your webpack.config.js file and add an entry to your rules to handle .html extensions:
{
test: /\.(html)$/,
exclude: /(node_modules)/,
use: {
loader: "html-loader"
}
}
Then you can import your .html files like you would components:
import Destination from '/path/to/destination.html'
Now treat component as an Object and leverage the template property to serve static HTML files:
{
path: '/destination',
mode: history,
name: 'destination',
component: { template: Destination }
}
1.install html-loader
npm install --save-dev html-loader
2.use below code vue.config.js or Webpack.config.js
For webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.html$/i,
loader: 'html-loader',
},
],
},
};
For Vue cli users vue.config.js
module.exports = {
chainWebpack: config => {
config.module
.rule('html')
.test(/\.html$/)
.use('html-loader')
.loader('html-loader')
}
}
just add router in your
{
path: '/print',
name: 'print',
component: () => import('../pages/print.html'),
},
more about vue
https://cli.vuejs.org/guide/webpack.html#replacing-loaders-of-a-rule
Related
In our web app we have a few JSON files that are ~10-80k lines each. These are getting included in our main bundle. These are used by an animation plugin called react-lottie.
An example of our webpack.config.js
module.exports = {
entry: ["./src/index.js"],
module: {
rules: [
{ test: /\.(js|jsx)$/, exclude: /node_modules/, use: ["babel-loader"] },
{
test: /\.(jpg|png|gif|ico)$/,
use: {
loader: "file-loader",
options: { name: "[path][name].[hash].[ext]" }
}
}
]
},
resolve: { extensions: ["*", ".js", ".jsx"] },
output: {
path: __dirname + "/dist",
publicPath: "/",
filename: "[name].[hash].js"
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new HtmlWebpackPlugin({ hash: false, template: "src/index.html" }),
new DashboardPlugin(),
new CopyWebpackPlugin([
{
from: "src/components/Assets/BookingBar.js",
to: "assets/BookingBar.js"
}
]),
new BundleAnalyzerPlugin()
],
devServer: {
contentBase: "./dist",
hot: true,
historyApiFallback: true,
port: 4000
}
};
What is the expected behavior?
There should be a way to exclude .json files from the main bundle. I've tried File-Loader, json-loader, and const someJson = require(./someJson)
Other relevant information:
webpack version: 4.16.1
Node.js version: 10.12.0
Operating System: Mac OS 10.14 Mojave
ANSWER BELOW (AT LEAST FOR HOW I SOLVED IT). I couldn't initialize the lottie without any data.
The expected behavior is that the JSON will get bundled because it's, presumably, needed synchronously at runtime. JSON data differs from something like image files which are loaded asynchronously by the browser as they are rendered on the page via src attributes etc.
As the comments mentioned, you should be using code splitting. The latest version of Webpack supports dynamic imports if you install and use the #babel/plugin-syntax-dynamic-import plugin.
npm install --save-dev #babel/plugin-syntax-dynamic-import
Then in babel.config.js:
module.exports = {
...
plugins: [
"#babel/plugin-syntax-dynamic-import"
]
...
};
Example
Say you have a React component that might need some JSON data, but doesn't need to load it synchronously as part of the bundle. Your non-code splitted version might look something like this:
import React from 'react';
import myJSON from './myJSON.json';
export default class MyComponent extends React.Component {
render() {
return <div>{JSON.stringify(myJSON, null, 2)}</div>
}
}
Instead you can use a dynamic import - basically a runtime import that returns a Promise you can use to asynchronously load some data chunked separately from your bundle:
import React from 'react';
import myJSON from './myJSON.json';
export default class MyComponent extends React.Component {
state = {data: {}};
componentDidMount() {
import(/* webpackChunkName: 'myJSON' */ './myJSON.json')
.then((data) => {
this.setState({data});
});
}
render() {
return <div>{JSON.stringify(this.state.data, null, 2)}</div>
}
}
Alternately, you can use React's new lazy and Suspense API (v16.6.0 and higher) to dynamically import React components that get chunked separately from the bundle. This might be preferable if you want to chunk a component and its corresponding JSON data together, but separately from the main bundle:
// MyComponent.jsx
import React from 'react';
import myJSON from './myJSON.json';
export default class MyComponent extends React.Component {
render() {
return <div>{JSON.stringify(myJSON, null, 2)}</div>
}
}
// SomeParent.jsx
import React, {lazy, Suspense} from 'react';
const MyComponent = lazy(() => import(/* webpackChunkName: 'MyComponent' */ './MyComponent'));
export default class SomeParent extends React.Component {
render() {
return <div>
<Suspense fallback={<div>Loading...<div>} >
<MyComponent />
</Suspense>
</div>;
}
}
In the above example, <MyComponent /> and its corresponding code -- including the JSON data -- will only be loaded when the component is actually rendered at runtime.
Ultimately I took the answer above below me but wasn't able to initialize the lottie without any JSON data. I ended up doing this:
import React, { PureComponent } from "react"
import Lottie from 'react-lottie'
export default class AnimationAutomatedCommunication extends PureComponent {
constructor(props) {
super(props)
this.state = {
animation: <div />
}
}
async componentDidMount() {
const animation = await import(/* webpackChunkName: "AnimationAutomatedCommunication" */ './JsonData/AnimationAutomatedCommunication.json')
const defaultOptions = {
loop: true,
autoplay: true,
animationData: animation.default
}
this.setState({
animation: <div className={this.props.className}>
<Lottie key="lottie-win-jobs" options={defaultOptions}
isStopped={this.props.isStopped} />
</div>
})
}
render() {
return (
<React.Fragment>
{this.state.animation}
</React.Fragment>
)
}
}
Webpack compilation fails throwing Cannot read property 'loadChildren' of undefined.
This Happens when i try to load routes from some function like below
export const routes: Routes = getRoutes();
function getRoutes() {
return [{ path: 'homepage', component: HomeComponent }];
}
When i export routes normally the webpack compilation will be successful.like below,
export const routes: Routes = [{ path: 'homepage', component: HomeComponent }];
And am mounting these routes in lazy loaded module.
As a guess, the getRoutes function should be exported as well. AoT doesn't know how to compile when declaration is hidden.
So try
export function getRoutes() {
return [{ path: 'homepage', component: HomeComponent }];
}
After starting webpack-dev-server, I can go directly to a static route (e.g. http://localhost:3456/one), but I cannot go directly to a dynamic route (e.g. http://localhost:3456/two/1234).
I believe I am missing something in my webpack-dev-server config, but not sure what.
The browser console outputs this error:
GET http://localhost:3456/two/dev-bundle.js 404 (Not Found)
Refused to execute script from 'http://localhost:3456/two/dev-bundle.js' because its MIME type ('text/html') is not executable, and strict MIME type checking is enabled
webpack.config.js
const path = require("path")
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require("webpack")
module.exports = {
mode: "development",
devtool: "eval-source-map",
entry: [
"./index.js",
],
output: {
filename: "dev-bundle.js",
},
module: {
rules: [
{
test: /\.jsx?$/,
loader: "babel-loader",
exclude: /node_modules/,
},
],
},
plugins: [
new HtmlWebpackPlugin({
template: path.join(__dirname, "dev.html")
}),
new webpack.NamedModulesPlugin(),
new webpack.HotModuleReplacementPlugin()
],
devServer: {
historyApiFallback: true,
hot: true,
port: 3456,
stats: "minimal"
}
}
app.js
import React, { Component } from "react"
import { hot } from "react-hot-loader"
import { BrowserRouter as Router, Switch, Route } from "react-router-dom"
import ComponentOne from "./components/ComponentOne"
import ComponentTwo from "./components/ComponentTwo"
const MyApp = () => (
<div>
<Router>
<Switch>
<Route exact path="/" component={ComponentOne} />
<Route exact path="/one" component={ComponentOne} />
<Route path="/two/:id" component={ComponentTwo} />
</Switch>
</Router>
</div>
)
export default hot(module)(MyApp)
ComponentTwo.js
import React, { Component } from "react"
import { Link } from "react-router-dom"
export default class ComponentTwo extends Component {
render() {
return (
<div>
<h1>ComponentTwo for {this.props.match.params.id}</h1>
</div>
)
}
}
Any help is appreciated.
I was able to resolve this by updating part of the webpack config:
output: {
filename: "dev-bundle.js",
publicPath: "/", // added this line
},
The console error remains, but at least the page loads.
I'm starting with webpack, but I'm really new on this and I'm stuck right now.
My project copies my fonts correctly but not images. Now the only way I am able to make it work is by copying my images manually to the dist/img folder.
This is my config:
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require("extract-text-webpack-plugin");
var webpack = require('webpack');
var path = require("path");
module.exports = {
entry: './src/app.js',
output: {
path: path.resolve(__dirname + '/dist'),
filename: 'app.bundle.js'
// publicPath: '/dist',
},
module: {
rules:[
{
test:/\.scss$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: ["css-loader?sourceMap","resolve-url-loader","sass-loader?sourceMap"],
// publicPath: '/dist'
})
},
{
test: /\.(woff2?|ttf|otf|eot|svg)$/,
use: [{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'fonts/'
}
}]
// loader: 'file-loader?name=/fonts/[name].[ext]'
},
{
test: /\.(jpg|png|gif)$/,
use: [{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'img/',
publicPath:'img/'
}
}]
}
]
},
devServer: {
contentBase: path.join(__dirname, "/dist"),
compress: true,
port: 8000,
stats: "errors-only",
open: true
},
plugins: [
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery'
}),
new ExtractTextPlugin("styles.css"),
new HtmlWebpackPlugin({
title: 'Project',
hash:true,
template: './src/index.html'
})
]
}
I've tried several configurations but no solution. I also searched here for any solution but without success.
If your images are only referenced in HTML files as <img> tags, webpack by default won't pick them up because it doesn't parse HTML. You have at least 2 choices:
Use CopyWebpackPlugin to copy the files to wherever you want, this at least removes the "manual" part you mention
Move your images references to styles, where webpack can pick them up via the scss loader you are using. For example
background-image: url("img/foo.png");
There is also option import image trough JavaScript.
import '../img/image.png';
I had this problem. I didn't know that the file-loader only copies the images if you run a build, and doesn't do anything while using webpack-dev-server. My solution was just:
$ npx webpack
I have a structure like this but am having an error when trying to run webpack
/app
/main.js
/foo.js
/dist
index.html ( uses <script src="dist/bundle.js"></script>)
webpackconfig.js
in main.js:
import foo from './foo'
var foo = new foo()
foo.js:
export class foo {
constructor() {
loadScript("//www.parsecdn.com/js/parse-1.4.0.min.js", init());
}
}
webpackconfig.js
My config:
module.exports = {
context: __dirname + "/app",
entry: "./main.js",
output: {
path: __dirname + "/dist",
filename: "bundle.js"
},
devtool: "#source-map",
module: {
loaders: [
// Transpile any JavaScript file:
{ test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader'}
]
},
resolve: {
// you can now require('file') instead of require('file.js')
extensions: ['', '.js', '.json']
}
}
but I get this error:
ERROR in ./main.js
Module not found: Error: Cannot resolve module 'foo'
It is because webpack try to load foo from node_modules directory.
You have to specify the path of your module like this:
import foo from './foo'