I'm trying to use Prism.js syntax highlighter client-side as an npm dependency, instead of loading it from <script src="..."> tags. Here is the Prism reference in package.json
{
"dependencies": {
"prismjs": "^1.5.1"
}
}
And the way I'm trying to use it in my code
import Prism from 'prismjs'
Prism.highlightAll();
This produces the following results:
Tokenizing works for basic languages (html, javascript...)
Tokenizing does not work for other specific languages (lua, handlebars...)
For all languages, syntax coloring isn't applied (css file doesn't seem loaded)
So I'm wondering
Are there other language-specific packages (like prismjs-handlebars for instance)?
Are there theme-specific packages (like prism-okaidia for instance) which would import the css?
--
TL;DR
How to load/use Prism.js client-side from npm instead of from script tags?
I eventually found the way to do this.
1. Add style-loader and css-loader to package.json
{
"dependencies": {
"style-loader": "^0.13.1",
"css-loader": "^0.23.0",
"prismjs": "^1.5.1"
}
}
2. Load css files in webpack.config.js
module: {
loaders: [
{
test: /\.css/,
loader: 'style-loader!css-loader'
}
]
}
3. Import desired files in the application
import Prism from 'prismjs'
import 'prismjs/themes/prism-okaidia.css'
import 'prismjs/components/prism-handlebars.min.js'
import 'prismjs/components/prism-lua.min.js'
Prism.highlightAll();
Related
I'm playing with Vue CLI project. I have configured startup project, set some development changes like those:
package.json
"dependencies": {
"bootstrap": "^4.3.1",
"core-js": "^3.0.1",
"preload-it": "^1.2.2",
"register-service-worker": "^1.6.2",
"vue": "^2.6.10",
"vue-router": "^3.0.3",
"vuetify": "^1.5.14",
"vuex": "^3.1.1"
},
"devDependencies": {
"#vue/cli-plugin-babel": "^3.7.0",
"#vue/cli-plugin-pwa": "^3.7.0",
"#vue/cli-service": "^3.7.0",
"fontello-cli": "^0.4.0",
"node-sass": "^4.9.0",
"sass-loader": "^7.1.0",
"stylus": "^0.54.5",
"stylus-loader": "^3.0.2",
"vue-cli-plugin-vuetify": "^0.5.0",
"vue-template-compiler": "^2.5.21",
"vuetify-loader": "^1.2.2"
}
vue.config.js
module.exports = {
configureWebpack: {
devtool: process.env.NODE_ENV === 'development'
? 'inline-source-map'
: false,
},
css: {
sourceMap: process.env.NODE_ENV === 'development'
}
}
babel.config.js
module.exports = {
presets: [
[
'#vue/app',
{ useBuiltIns: 'entry' }
]
]
}
But sourcemaps to vue files are still generated wrongly (to scss files works ok).
After clicking href to vue component
Note:
lot of versions of same file in webpack://./
only part that is in tag is visibile in source editor (maybe this is a cause)
file from mounted filesystem workspace is not used
And this is how original file looks like - it is possible to edit it via Chrome devtools
Is it possible to fix that so also element inspector tab (style) will provide proper source target?
EDIT 1
Simplest setup:
Install Vue CLI (3.7)
Add my vue.config.js (to enable sourcemaps)
Run npm run serve
EDIT 2
Same for Vue CLI 3.5
I also created repo with test project, but like I wrote it is just startup project with my config.
https://github.com/l00k/vue-sample
EDIT 3
Vue-cli github issue
https://github.com/vuejs/vue-cli/issues/4029
So far I did not found solution - at least using Vue CLI.
But I have found workaround.
But first of all - whole problem is not about Vue CLI but it is something with vue-loader-plugin IMO. I think so because while using clean setup with vue and webpack I also see that problem.
I have found out that it is related to wrong sourcemap generated for those parts of Vue file and
Source for those part is strip to only content of those tags. That is probably why browser could not map it to source. Also path to source file in sourcemap is wrong.
I have prepared additional loader for webpack which fixes those sourcemaps.
Check sm-fix-loader in repo below.
I dont know does it fix all issues, but at least in my cases it works awesome.
What works ok:
Build NODE_ENV=development webpack
SCSS inline (in vue file) and in separate file <style src="...">
TS / JS inline (in vue file) and in separate file <script src="...">
HRM NODE_ENV=development webpack-dev-server --hotOnly
SCSS inline (in vue file) and in separate file <style src="...">
It also reloads styles without reloading page itself :D
TS / JS inline (in vue file) and in separate file <script src="...">
Repo with working example:
https://github.com/l00k/starter-vue
Step by step solution:
Enable css sourcemaps in vue.config.js:
module.exports = {
css: {sourceMap: true},
Move all scss from components to separate files, collate them in index.scss and import index.scss via App.vue. This will solve lots of problems with vue-css-sourcemaps (caused by Webpack, Devtools and vue-cli), and somewhat simplify your workflow. If you need scoping, scope manually via #selectors (Importing SCSS file in Vue SFC components without duplication with Webpack)
To go further, you may need to set up CSS extraction for node_modules only, as another mysterious bug ruins styling as soon as you touch any css in devtools:
devtool: 'cheap-source-map',
plugins: process.env.NODE_ENV === 'development' ?
([new MiniCssExtractPlugin()]) : [],
module: {
rules: [
process.env.NODE_ENV === 'development' ?
(
{
// test: /node_modules/,
test: /node_modules\/.+\.scss/,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
importLoaders: 2,
sourceMap: true
}
},
{
loader: 'postcss-loader',
options: {
plugins: () => [require('autoprefixer')],
sourceMap: true
}
},
{
loader: 'sass-loader',
options: {sourceMap: true}
}
]
}) : {}
],
}
If you extract all css, you'll loose hmr (hot module reloading = reload on edit), but since you don't really edit scss in your node_modules, you extact only them.
All in all, this fixed all vue css-related sourcemap issues with Devtools and enabled hot-editing right in browser.
I'm grokking my way through ES6 and I ran into Modules (nice!) and in learning, I am trying to see if I can use them in the browser without WebPack (which I haven't learned yet).
So, I have the following files/folder structure in my JS directory
js
- lib (for complied es6 via Babel)
- mods (compiled modules)
- module.js (compiled via Babel)
- app.js (imports modules, attached to index.html)
- src (for "raw" es6)
- mods (es6 modules)
- module.js (es6 module)
- app.js (imports modules)
In js/src/mods/module.js, I have the following code....
export const topTime = 1.5;
export const subTime = 0.75;
Which is imported by js/src/app.js ...
import { topTime, subTime } from './mods/modules';
console.log(topTime);
console.log(subTime);
I then compiled all es6 files to es5 (which placed the files in the lib dir.)
npm run babel
Now I can run the main file (js/lib/app.js) inside my editor (vscode/output tab)
[Running] node "/home/me/www/es6.local/js/lib/app.js"
1.5
0.75
...but I think that is only because it's running in node.
It breaks when I call my index.html file (with js/lib/app.js) in the browser (FF) as I get the following error...
ReferenceError: require is not defined
So I see that babel compiled this...
import { topTime, subTime } from './mods/modules';
into this...
var _modules = require('./mods/modules');
...But I thought this was valid es5? ...no? So HOW was this done BEFORE webpack? Please advise.
Here is my package.json (in case it helps)...
{
"name": "es6.local",
"version": "0.0.1",
"description": "JavaScript ES6 Testing Sandbox",
"main": "index.html",
"scripts": {
"babel": "babel js/src --out-dir js/lib --source-maps"
},
"author": "Student",
"license": "ISC",
"devDependencies": {
"eslint": "^4.16.0",
"eslint-plugin-import": "^2.8.0",
"eslint-plugin-jsx-a11y": "^6.0.3",
"eslint-plugin-react": "^7.6.0",
"eslint-config-airbnb": "^16.1.0",
"babel-cli": "^6.26.0",
"babel-polyfill": "^6.26.0",
"babel-preset-env": "^1.6.1"
},
"babel": {
"presets": [
[
"env",
{
"targets": {
"browsers": [
"last 2 versions",
"safari >= 7"
]
}
}
]
]
}
}
I've been stuck with this for a while and after playing around I found a solution.
You don't need any libraries or webpack to do this and I'm not sure this works outside of chrome.
You need to run this code on a webserver or else it won't work (in other words, it has to be on localhost, NOT file://)
Make a folder called jsmodule
create a file called index.html with the following code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Js module</title>
</head>
<body>
<h1>JS module test</h1>
<script type="module" src="script.js"></script>
</body>
</html>
Create a file in same folder called script.js with the following code:
import Person from './Person.js';
import Book from './Book.js';
let person1 = new Person();
let someBook = new Book();
create a file in same folder called Person.js with the following code:
export default class Person{
constructor(){
alert("hallo from person");
}
}
create a file in same folder called Book.js with the following code:
export default class Book{
constructor(){
alert("Hallo from book");
}
}
Run the index.html on you webserver (localhost)
In the HTML
script src="/my-script.js" type="module">
In the script
import axios from './axios.js';
The script tag in the HTML needs to have the type of module, else the parser will not understand what import is.
The import statement needs to have the full path to the JS file you’re importing (relative paths should be fine): you cannot do import axios from 'axios' because that’s just a string — the browser has no idea if that’s even a file or where that file is.
The browser has no idea what NPM is. It’s a package manager for Node, it’s not connected to JavaScript in general. You need the actual file (which you could use NPM to add to your project, then the path will be something like ./node_modules/axios/dist/axios.js
but even using this could create some problem as it some internal dependency over some packages or libraries in node_modules folder
I would recommend using webpack or any blunder tool
which auto-magically use NPM modules then bundle everything up into a single output file.
It's a pain.
exports and require are part of the CommonJS spec. If I remember correctly, webpack implements it internally. You need the same functionality, because it's not part of ES5.
Try RequireJS, or something similar to load your modules.
I have a simple project set up using TypeScript, ReactJS, and SASS, and would like to bundle it all using Webpack. There's plenty of documentation on how to achieve this with JavaScript and regular old CSS. However, I can't find any documentation that combines the loaders I need and uses Webpack 2 syntax (rather than the original Webpack syntax for loaders). Thus, I'm unsure of how to create the correct configuration.
You can find my webpack.config.js file here. How would I modify the configuration so that TypeScript accepts my SCSS modules, and so that Webpack properly bundles my SCSS with my TypeScript?
This may also be helpful: when I run Webpack at the moment, I get the following error:
ERROR in ./node_modules/css-loader!./node_modules/typings-for-css-modules-loader/lib?{"namedExport":true,"camelCase":true}!./node_modules/sass-loader/lib/loader.js!./src/raw/components/styles.scss
Module build failed: Unknown word (1:1)
> 1 | exports = module.exports = require("../../../node_modules/css-loader/lib/css-base.js")(undefined);
| ^
2 | // imports
3 |
4 |
# ./src/raw/components/styles.scss 4:14-206
# ./src/raw/components/greetings/greetings.tsx
# ./src/raw/index.tsx
# multi ./src/raw/index.tsx
ERROR in [at-loader] ./src/raw/components/greetings/greetings.tsx:3:25
TS2307: Cannot find module '../styles.scss'.
Note that ./src/raw/index.tsx is the entry point of my application, ./src/raw/components/greetings/greeting.tsx is my only React component, and ./src/raw/components/styles.scss is my only SCSS file.
The typings-for-css-modules-loader is a drop-in replacement for css-loader (technically it uses css-loader under the hood) and that means it takes CSS and transforms it to JavaScript. You're also using the css-loader, and that fails because it receives JavaScript, but expected CSS (as JavaScript is not valid CSS, it fails to parse).
Additionally, you are not using CSS modules, because you're not setting the modules: true option on the CSS loader (or typings-for-css-modules-loader, which passes it on to css-loader).
Your .scss rule should be:
{
test: /\.scss$/,
include: [
path.resolve(__dirname, "src/raw")
],
use: [
{ loader: "style-loader" },
{
loader: "typings-for-css-modules-loader",
options: {
namedexport: true,
camelcase: true,
modules: true
}
},
{ loader: "sass-loader" }
]
}
Here is a little extended version (since the above did somehow not work for me), using another package (css-modules-typescript-loader) derived from the stale typings-for-css-modules-loader.
In case anybody runs into the same problems - this is a configuration that works for me:
TypeScript + WebPack + Sass
webpack.config.js
module.exports = {
//mode: "production",
mode: "development", devtool: "inline-source-map",
entry: [ "./src/app.tsx"/*main*/ ],
output: {
filename: "./bundle.js" // in /dist
},
resolve: {
// Add `.ts` and `.tsx` as a resolvable extension.
extensions: [".ts", ".tsx", ".js", ".css", ".scss"]
},
module: {
rules: [
{ test: /\.tsx?$/, loader: "ts-loader" },
{ test: /\.scss$/, use: [
{ loader: "style-loader" }, // to inject the result into the DOM as a style block
{ loader: "css-modules-typescript-loader"}, // to generate a .d.ts module next to the .scss file (also requires a declaration.d.ts with "declare modules '*.scss';" in it to tell TypeScript that "import styles from './styles.scss';" means to load the module "./styles.scss.d.td")
{ loader: "css-loader", options: { modules: true } }, // to convert the resulting CSS to Javascript to be bundled (modules:true to rename CSS classes in output to cryptic identifiers, except if wrapped in a :global(...) pseudo class)
{ loader: "sass-loader" }, // to convert SASS to CSS
// NOTE: The first build after adding/removing/renaming CSS classes fails, since the newly generated .d.ts typescript module is picked up only later
] },
]
}
};
Also put a declarations.d.ts in your project:
// We need to tell TypeScript that when we write "import styles from './styles.scss' we mean to load a module (to look for a './styles.scss.d.ts').
declare module '*.scss';
And you will need all these in your package.json's dev-dependencies:
"devDependencies": {
"#types/node-sass": "^4.11.0",
"node-sass": "^4.12.0",
"css-loader": "^1.0.0",
"css-modules-typescript-loader": "^2.0.1",
"sass-loader": "^7.1.0",
"style-loader": "^0.23.1",
"ts-loader": "^5.3.3",
"typescript": "^3.4.4",
"webpack": "^4.30.0",
"webpack-cli": "^3.3.0"
}
Then you should get a mystyle.d.ts next to your mystyle.scss containing the CSS classes you defined, which you can import as a Typescript module and use like this:
import * as styles from './mystyles.scss';
const foo = <div className={styles.myClass}>FOO</div>;
The CSS will automatically be loaded (injected as a style element into the DOM) and contain cryptic identifiers instead of your CSS classes in the .scss, to isolate your styles in the page (unless you use :global(.a-global-class) { ... }).
Note that the first compile will fail whenever you add CSS classes or remove them or rename them, since the imported mystyles.d.ts is the old version and not the new version just generated during compilation. Just compile again.
Enjoy.
I'm trying to use Vueify in my first Laravel project and I'm not sure as to why it isn't working.
I've installed (via npm) both vueify and laravel-elixir-vueify modules.
gulpfile.js
const elixir = require('laravel-elixir');
require('laravel-elixir-vue-2');
require('laravel-elixir-browserify-official');
require('laravel-elixir-vueify');
elixir(function(mix) {
mix.scripts([
'vendor/vue.min.js',
'vendor/vue-resource.min.js'
], 'public/js/vendor.js')
.sass('app.scss')
.webpack('app.js');
});
app.js
import Vue from 'Vue';
import Chart from './components/Chart.vue';
Vue.component('chart', Chart);
My console is giving me the error: Unknown custom element: <chart> any ideas on what isn't working or what I've missed? I've become a bit confused about what I need to install or how to include things. I've also got a handful of pages which each have their own .js file under /public/js/. I'm not sure if this is good or bad practice with regards to using elixir. But if it's not a bad way to do it ideally I'd want to import the .vue files from /resources/assets/js/components/ to those js files so that I only have to load in the ones which are relevant to each page. But I'm really not sure if that's the wrong way to go about it. Any ideas? I've searched around for answers but nothing seems to have helped me yet.
Just for testing my Chart.vue file looks like this.
Chart.vue
<template id="learnometer-chart">
<div id="myPieChart" style="width:1000px; height:1000px; background-color:red;"></div>
</template>
<script>
</script>
Assuming that you are using Laravel 5.3 and Vue 2.0, you can now compile with webpack.
gulpfile.js
const elixir = require('laravel-elixir');
require('laravel-elixir-vue-2');
elixir(function(mix) {
mix.webpack('app.js');
}
Register your components on your resources/assets/js/app.js:
require('./bootstrap');
Vue.component(
'chart',
require('./components/Chart.vue')
);
const app = new Vue({
el: '#app'
});
Your components should be inside resources/assets/js/components.
The package.json should look something like:
{
"private": true,
"scripts": {
"prod": "gulp --production",
"dev": "gulp watch"
},
"devDependencies": {
"bootstrap-sass": "^3.3.7",
"gulp": "^3.9.1",
"jquery": "^3.1.0",
"laravel-elixir": "^6.0.0-11",
"laravel-elixir-vue-2": "^0.2.0",
"laravel-elixir-webpack-official": "^1.0.2",
"lodash": "^4.16.2",
"vue": "^2.0.1",
"vue-resource": "^1.0.3"
}
}
When you have this, run npm install or npm install --no-bin-links if you are on Windows. Now you can run gulp to compile your vue files.
I'm failing to figure out how to setup my webpack in order to be able and use scss modules inside my components like:
import styles from './ComponentStyles.scss'
So far I tried configuring webpack to use sass-loader alongside postcss-loader but had no luck:
{
test: /\.scss$/,
loaders: [
'isomorphic-style-loader',
'css-loader?modules&localIdentName=[name]_[local]_[hash:base64:3]',
'postcss-loader',
'scss-loader'
]
}
Note isomorphic-style-loader is a library I use instead of style-loader due to server rendering requirements, in its github page docs they actually use postcss-loader with .scss extension, but in my case scss is not compiled if I follow their example.
I had to do some tinkering myself, but eventually landed on the following
package.json
"autoprefixer": "^6.3.1",
"css-loader": "^0.23.1",
"extract-text-webpack-plugin": "^1.0.1",
"node-sass": "^3.8.0",
"sass-loader": "^3.1.2",
"style-loader": "^0.13.0"
webpack config
...
const autoprefixer = require('autoprefixer');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const autoprefixer = require('autoprefixer');
...
const config = {
...
postcss: [
autoprefixer({
browsers: ['last 2 versions']
})
],
plugins: [
new ExtractTextPlugin('css/bundle.css'),
],
module: {
loaders: [
{
test: /\.scss$/,
loader: ExtractTextPlugin.extract('style', 'css!postcss!sass')
}
]
}
...
};
bootstrap.jsx
import React from 'react';
import ReactDOM from 'react-dom';
import App from './app';
import style from './scss/style.scss';
ReactDOM.render(
<App/>,
document.getElementById('my-app')
);
For those interested: what's happening here is bootstrap.jsx is the webpack entry point, and by importing our raw scss file (via relative path), we tell webpack to include it during the build process.
Also, since we've specified a loader for this file extension in our configuration (.scss), webpack is able to parse style.scss and run it through the defined loaders from right to left: sass --> post-css --> css.
We then use extract-text-webpack-plugin to pull the compiled CSS out from bundle.js, where it would normally reside, and place it in a location (css/bundle.css) relative to our output directory.
Also, using extract-text-webpack-plugin is optional here, as it will simply extract your CSS from bundle.js and plop it in a separate file, which is nice if you utilize server-side rendering, but I also found it helpful during debugging, since I had a specific output location for the scss I was interested in compiling.
If you're looking to see this in action, here's a small boilerplate that uses it: https://github.com/mikechabot/react-boilerplate