web worker example

This commit is contained in:
dotnetCarpenter 2018-03-18 01:45:52 +01:00
parent 56bcd609fd
commit cd9a6c2c05
17 changed files with 499 additions and 0 deletions

View File

@ -0,0 +1,21 @@
module.exports = {
root: true,
env: {
browser: true,
node: true
},
parserOptions: {
parser: 'babel-eslint'
},
extends: [
// https://github.com/vuejs/eslint-plugin-vue#priority-a-essential-error-prevention
// consider switching to `plugin:vue/strongly-recommended` or `plugin:vue/recommended` for stricter rules.
'plugin:vue/strongly-recommended'
],
// required to lint *.vue files
plugins: [
'vue'
],
// add your custom rules here
rules: {}
}

11
examples/web-worker/.gitignore vendored Normal file
View File

@ -0,0 +1,11 @@
# dependencies
node_modules
# logs
npm-debug.log
# Nuxt build
.nuxt
# Nuxt generate
dist

View File

@ -0,0 +1,26 @@
# web-worker
> Nuxt.js project
In nuxt 1.4 and below you have to create a production build to use web workers.
## Build Setup
``` bash
# install dependencies
$ npm install # Or yarn install
# serve with hot reload at localhost:3000
# nuxt 1.4 and below does not support web workers in dev mode
$ npm run dev
# build for production and launch server
# in nuxt 1.4 and below you have to create a production build to use web workers
$ npm run build
$ npm start
# generate static project
$ npm run generate
```
For detailed explanation on how things work, checkout the [Nuxt.js docs](https://github.com/nuxt/nuxt.js).

View File

@ -0,0 +1,8 @@
# ASSETS
This directory contains your un-compiled assets such as LESS, SASS, or JavaScript.
More information about the usage of this directory in the documentation:
https://nuxtjs.org/guide/assets#webpacked
**This directory is not required, you can delete it if you don't want to use it.**

View File

@ -0,0 +1,17 @@
// // block for `time` ms, then return the number of loops we could run in that time:
function expensive(time) {
let start = Date.now(),
count = 0
while (Date.now() - start < time) count++
return count
}
// Respond to message from parent thread
self.addEventListener('message', (event) => {
console.log('worker', event.data)
if (event.data.action === 'expensive' && event.data.time) {
// Post data to parent thread
self.postMessage(expensive(Number(event.data.time)))
}
})

View File

@ -0,0 +1,79 @@
<template>
<div class="VueToNuxtLogo">
<div class="Triangle Triangle--two"/>
<div class="Triangle Triangle--one"/>
<div class="Triangle Triangle--three"/>
<div class="Triangle Triangle--four"/>
</div>
</template>
<style>
.VueToNuxtLogo {
display: inline-block;
animation: turn 2s linear forwards 1s;
transform: rotateX(180deg);
position: relative;
overflow: hidden;
height: 180px;
width: 245px;
}
.Triangle {
position: absolute;
top: 0;
left: 0;
width: 0;
height: 0;
}
.Triangle--one {
border-left: 105px solid transparent;
border-right: 105px solid transparent;
border-bottom: 180px solid #41B883;
}
.Triangle--two {
top: 30px;
left: 35px;
animation: goright 0.5s linear forwards 3.5s;
border-left: 87.5px solid transparent;
border-right: 87.5px solid transparent;
border-bottom: 150px solid #3B8070;
}
.Triangle--three {
top: 60px;
left: 35px;
animation: goright 0.5s linear forwards 3.5s;
border-left: 70px solid transparent;
border-right: 70px solid transparent;
border-bottom: 120px solid #35495E;
}
.Triangle--four {
top: 120px;
left: 70px;
animation: godown 0.5s linear forwards 3s;
border-left: 35px solid transparent;
border-right: 35px solid transparent;
border-bottom: 60px solid #fff;
}
@keyframes turn {
100% {
transform: rotateX(0deg);
}
}
@keyframes godown {
100% {
top: 180px;
}
}
@keyframes goright {
100% {
left: 70px;
}
}
</style>

View File

@ -0,0 +1,6 @@
# COMPONENTS
The components directory contains your Vue.js Components.
Nuxt.js doesn't supercharge these components.
**This directory is not required, you can delete it if you don't want to use it.**

View File

@ -0,0 +1,8 @@
# LAYOUTS
This directory contains your Application Layouts.
More information about the usage of this directory in the documentation:
https://nuxtjs.org/guide/views#layouts
**This directory is not required, you can delete it if you don't want to use it.**

View File

@ -0,0 +1,58 @@
<template>
<div>
<nuxt/>
</div>
</template>
<style>
html {
font-family: "Source Sans Pro", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
font-size: 16px;
word-spacing: 1px;
-ms-text-size-adjust: 100%;
-webkit-text-size-adjust: 100%;
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
box-sizing: border-box;
}
*, *:before, *:after {
box-sizing: border-box;
margin: 0;
}
.button {
margin-left: 15px;
cursor: pointer;
user-select: none;
}
.button--green {
display: inline-block;
border-radius: 4px;
border: 1px solid #3b8070;
color: #3b8070;
text-decoration: none;
padding: 10px 30px;
}
.button--green:hover {
color: #fff;
background-color: #3b8070;
}
.button--grey {
display: inline-block;
border-radius: 4px;
border: 1px solid #35495e;
color: #35495e;
text-decoration: none;
padding: 10px 30px;
}
.button--grey:hover {
color: #fff;
background-color: #35495e;
}
</style>

View File

@ -0,0 +1,49 @@
module.exports = {
/*
** Headers of the page
*/
head: {
title: 'web-worker',
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ hid: 'description', name: 'description', content: 'Nuxt.js project' }
],
link: [
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
]
},
/*
** Customize the progress bar color
*/
loading: { color: '#3B8070' },
plugins: [
{ src: '~/plugins/inject-ww', ssr: false } // web workers are only available client-side, hence ssr: false
],
/*
** Build configuration
*/
build: {
/*
** Run ESLint on save
*/
extend (config, { isDev, isClient }) {
if (isDev && isClient) {
config.module.rules.push({
enforce: 'pre',
test: /\.(js|vue)$/,
loader: 'eslint-loader',
exclude: /(node_modules)/
})
}
if (isClient) { // web workers are only available client-side
config.module.rules.push({
test: /\.worker\.js$/, // this will pick up all .js files that ends with ".worker.js"
loader: 'worker-loader',
exclude: /(node_modules)/
})
}
}
}
}

View File

@ -0,0 +1,21 @@
{
"name": "web-worker",
"description": "Demo web workers in nuxt.js",
"private": true,
"scripts": {
"dev": "nuxt",
"build": "nuxt build",
"start": "nuxt start",
"generate": "nuxt generate",
"lint": "eslint --ext .js,.vue --ignore-path .gitignore .",
"precommit": "npm run lint"
},
"dependencies": {
"eslint": "^4.19.0",
"nuxt": "^1.4.0"
},
"devDependencies": {
"eslint-plugin-vue": "^4.3.0",
"worker-loader": "^1.1.1"
}
}

View File

@ -0,0 +1,7 @@
# PAGES
This directory contains your Application Views and Routes.
The framework reads all the .vue files inside this directory and creates the router of your application.
More information about the usage of this directory in the documentation:
https://nuxtjs.org/guide/routing

View File

@ -0,0 +1,160 @@
<template>
<section class="container">
<div>
<app-logo/>
<h1 class="title">
web-worker
</h1>
<h2 class="subtitle">
Nuxt.js project
</h2>
<p>{{ notification }}</p>
<ul class="list">
<li>Number of Web Workers: {{ workers.length }}</li>
<li>Number of long Running Workers: {{ longRunningWorkers.length }}</li>
<li>Number of unused Workers: {{ workers.filter(w => !w.inUse).length }}</li>
</ul>
<div class="links">
<a
:class="needWorkerSetup ? 'hidden' : 'visible'"
@click="test"
class="button button--green">Test Worker</a>
<a
:class="needWorkerSetup ? 'hidden' : 'visible'"
@click="long(4000)"
class="button button--green">Execute long running Worker</a>
<a
:class="needWorkerSetup || !longRunningWorkers.length ? 'hidden' : 'visible'"
@click="freeWorker"
class="button button--green">Free long running Worker</a>
<a
@click="removeWorker"
class="button button--grey">Remove Web Worker</a>
<a
@click="createWorkers"
class="button button--grey">Create more Workers</a>
</div>
</div>
</section>
</template>
<script>
import AppLogo from '~/components/AppLogo.vue'
export default {
components: {
AppLogo
},
computed: {
needWorkerSetup () {
return this.workers.length === 0 && this.longRunningWorkers.length === 0
}
},
data () {
return {
notification: '',
workers: [],
workerIndex: 0,
longRunningWorkers: [],
longIndex: 0
}
},
watch: {
workers (workers) {
if (workers.length === 0) this.notification = 'Zero free Web Workers - click "Create more Workers"'
}
},
methods: {
test () {
const worker = this.workers[this.workerIndex++ % this.workers.length]
if (worker) worker.postMessage({ hello: 'world' })
else this.notification = 'No more test workers available'
},
long (miliseconds) {
let worker = this.workers.shift()
if (worker) {
worker.onmessage = (event) => {
console.log(`expensive made ${event.data} loops`)
}
this.longRunningWorkers.push(worker)
} else {
worker = this.longRunningWorkers[ this.longIndex++ % this.longRunningWorkers.length]
}
worker.postMessage({ action: 'expensive', time: miliseconds })
},
freeWorker () {
const worker = this.longRunningWorkers.pop()
worker.onmessage = null
this.workers.push(worker)
this.notification = 'Worker freed'
},
removeWorker () {
const worker = this.workers.pop() || this.longRunningWorkers.pop()
if (!worker) return
if (this.longRunningWorkers.indexOf(worker) > -1) this.longRunningWorkers.splice(this.longRunningWorkers.indexOf(worker), 1)
worker.onmessage = null
worker.terminate()
},
createWorkers () {
if (process.browser) {
for(let i = 0, len = navigator.hardwareConcurrency || 1; i < len; i++) {
this.workers.push(this.$worker.createWorker())
}
this.notification = 'Go nuts!'
}
}
}
}
</script>
<style>
.hidden {
visibility: hidden;
}
.visible {
visibility: visible;
}
.container {
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
text-align: center;
}
.title {
font-family: "Quicksand", "Source Sans Pro", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; /* 1 */
display: block;
font-weight: 300;
font-size: 100px;
color: #35495e;
letter-spacing: 1px;
}
.subtitle {
font-weight: 300;
font-size: 42px;
color: #526488;
word-spacing: 5px;
padding-bottom: 15px;
}
.links {
padding-top: 15px;
}
.list {
text-align: left;
color: #526488;
list-style: none;
}
</style>

View File

@ -0,0 +1,8 @@
# PLUGINS
This directory contains your Javascript plugins that you want to run before instantiating the root vue.js application.
More information about the usage of this directory in the documentation:
https://nuxtjs.org/guide/plugins
**This directory is not required, you can delete it if you don't want to use it.**

View File

@ -0,0 +1,9 @@
import ExampleWorker from '~/assets/js/Example.worker.js' // worker files has to end in ".worker.js" - see nuxt.config.js
export default (context, inject) => {
inject('worker', {
createWorker () {
return new ExampleWorker()
}
})
}

View File

@ -0,0 +1,11 @@
# STATIC
This directory contains your static files.
Each file inside this directory is mapped to /.
Example: /static/robots.txt is mapped as /robots.txt.
More information about the usage of this directory in the documentation:
https://nuxtjs.org/guide/assets#static
**This directory is not required, you can delete it if you don't want to use it.**

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB