使用 Webpack 实现 Vue SFC(无 Vue CLI)
Implementing Vue SFC with Webpack (no Vue CLI)
我最近切换到 Webpack,现在我的所有 JS 和 CSS 运行 都能完美地通过它。这是 webpack.config.js 的相关部分:
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: [
{
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
},
{loader: 'import-glob-loader'}
]
},
{
test: /\.scss$/,
exclude: /node_modules/,
use: [
{loader: MiniCssExtractPlugin.loader},
{loader: 'css-loader'},
{
loader: 'postcss-loader',
options: {
plugins: [
require('autoprefixer')
]
}
},
{loader: 'sass-loader'},
{loader: 'import-glob-loader'}
]
}
]
我从 CDN 中包含了 Vue,使用此设置我可以毫无问题地执行以下操作:
Vue.component('test-component', {
data: function () {
return {
title: 'Title',
description: 'Description'
};
},
methods: {
created: function () {
console.log('Created');
}
},
template: '<section id="test-component"><h2>{{ title }}</h2>{{ description }}</section>'
});
new Vue({el: '#app'});
在我的 HTML 中:
<div id="app">
<test-component></test-component>
</div>
我现在想改用 Vue 单文件组件,并阅读它告诉我通过 vue-loader 简单地 运行 .vue 文件的文档,所以我将我的规则更改为以下内容:
rules: [
// NOTE: This is new
{
test: /\.vue$/,
loader: 'vue-loader'
},
{
test: /\.js$/,
exclude: /node_modules/,
use: [
{
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
},
{loader: 'import-glob-loader'}
]
},
{
test: /\.scss$/,
exclude: /node_modules/,
use: [
{loader: MiniCssExtractPlugin.loader},
{loader: 'css-loader'},
{
loader: 'postcss-loader',
options: {
plugins: [
require('autoprefixer')
]
}
},
// NOTE: This is new too, but commented because it throws errors
// {loader: 'vue-style-loader'},
{loader: 'sass-loader'},
{loader: 'import-glob-loader'}
]
}
]
有了这个,我的 .vue 文件被拾取并添加到 dist/main.js 所以它似乎工作(只要我不包含 <style>
元素在Vue 文件,在这种情况下它会失败),但现在 new Vue({el: '#app'})
什么都不做。检查 DOM <test-component>
仍然在那里,根本没有被 Vue 渲染。
如果我也尝试启用 vue-style-loader
构建将完全失败并显示:
(1:4) Unknown word
> 1 | // style-loader: Adds some css to the DOM by adding a <style> tag
| ^
2 |
3 | // load the styles
我做错了什么?
编辑:进展。多亏了 Daniel,我的 <style>
现在只要设置了 lang="scss"
就可以使用。这是因为我的 webpack 配置只有 scss
个文件的规则,而不是 css
个文件的规则。
我也弄清楚了 <test-component>
不会呈现的原因是因为我从未真正注册过它,仅仅包括 .vue
-file 显然不足以让它注册.
我现在遇到的问题是尝试将我所有的 .vue
文件作为组件数组导入。如果我这样做,效果很好:
import TestComponent from "./test-component.vue";
import AnotherComponent from "./another-component.vue";
document.querySelectorAll('[data-vue]').forEach(el => {
new Vue({
el: el,
components: {
'test-component': TestComponent,
'another-component': AnotherComponent
}
});
});
但我希望能够以某种方式做到这一点:
import components from "./**/*.vue";
document.querySelectorAll('[data-vue]').forEach(el => {
new Vue({
el: el,
components: components
});
});
使用 import-glob-loader
.
确保您的 SFC 中有 <style lang="scss">
您也可以尝试删除 package-lock 和 node_modules 文件夹并进行全新安装。如果依赖项未使用兼容版本,有时这可以解决问题。
更新
要使用 glob 样式导入,您可能需要使用 import-glob
https://www.npmjs.com/package/import-glob
您也可以使用全局组件注册来实现类似的结果。这在官方文档中有很好的记录:
https://vuejs.org/v2/guide/components-registration.html#Automatic-Global-Registration-of-Base-Components
仅导入 vue
文件不足以使它们可供使用。您还必须使用 Vue 注册它们。
所以,这是错误的:
import 'component.vue';
new Vue({el: '#app'});
这是对的:
import component from 'component.vue';
new Vue({
el: '#app',
components: {
'component': component
}
});
这会确保它们可用。
<style>
元素不起作用的原因是因为我没有针对 CSS
文件的 webpack 规则 - 仅针对 SCSS
文件。感谢@Daniel 指出我需要 <style lang="scss">
.
vue-style-loader
只需要将样式注入 DOM 作为 <style>
元素,我实际上并不使用这些元素(我使用 mini-css-extract-plugin
创建 css
-文件)也根据文档:
However, since this is included as a dependency and used by default in vue-loader, in most cases you don't need to configure this loader yourself.
将创建一个关于 glob 导入的单独问题。
我最近切换到 Webpack,现在我的所有 JS 和 CSS 运行 都能完美地通过它。这是 webpack.config.js 的相关部分:
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: [
{
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
},
{loader: 'import-glob-loader'}
]
},
{
test: /\.scss$/,
exclude: /node_modules/,
use: [
{loader: MiniCssExtractPlugin.loader},
{loader: 'css-loader'},
{
loader: 'postcss-loader',
options: {
plugins: [
require('autoprefixer')
]
}
},
{loader: 'sass-loader'},
{loader: 'import-glob-loader'}
]
}
]
我从 CDN 中包含了 Vue,使用此设置我可以毫无问题地执行以下操作:
Vue.component('test-component', {
data: function () {
return {
title: 'Title',
description: 'Description'
};
},
methods: {
created: function () {
console.log('Created');
}
},
template: '<section id="test-component"><h2>{{ title }}</h2>{{ description }}</section>'
});
new Vue({el: '#app'});
在我的 HTML 中:
<div id="app">
<test-component></test-component>
</div>
我现在想改用 Vue 单文件组件,并阅读它告诉我通过 vue-loader 简单地 运行 .vue 文件的文档,所以我将我的规则更改为以下内容:
rules: [
// NOTE: This is new
{
test: /\.vue$/,
loader: 'vue-loader'
},
{
test: /\.js$/,
exclude: /node_modules/,
use: [
{
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
},
{loader: 'import-glob-loader'}
]
},
{
test: /\.scss$/,
exclude: /node_modules/,
use: [
{loader: MiniCssExtractPlugin.loader},
{loader: 'css-loader'},
{
loader: 'postcss-loader',
options: {
plugins: [
require('autoprefixer')
]
}
},
// NOTE: This is new too, but commented because it throws errors
// {loader: 'vue-style-loader'},
{loader: 'sass-loader'},
{loader: 'import-glob-loader'}
]
}
]
有了这个,我的 .vue 文件被拾取并添加到 dist/main.js 所以它似乎工作(只要我不包含 <style>
元素在Vue 文件,在这种情况下它会失败),但现在 new Vue({el: '#app'})
什么都不做。检查 DOM <test-component>
仍然在那里,根本没有被 Vue 渲染。
如果我也尝试启用 vue-style-loader
构建将完全失败并显示:
(1:4) Unknown word
> 1 | // style-loader: Adds some css to the DOM by adding a <style> tag
| ^
2 |
3 | // load the styles
我做错了什么?
编辑:进展。多亏了 Daniel,我的 <style>
现在只要设置了 lang="scss"
就可以使用。这是因为我的 webpack 配置只有 scss
个文件的规则,而不是 css
个文件的规则。
我也弄清楚了 <test-component>
不会呈现的原因是因为我从未真正注册过它,仅仅包括 .vue
-file 显然不足以让它注册.
我现在遇到的问题是尝试将我所有的 .vue
文件作为组件数组导入。如果我这样做,效果很好:
import TestComponent from "./test-component.vue";
import AnotherComponent from "./another-component.vue";
document.querySelectorAll('[data-vue]').forEach(el => {
new Vue({
el: el,
components: {
'test-component': TestComponent,
'another-component': AnotherComponent
}
});
});
但我希望能够以某种方式做到这一点:
import components from "./**/*.vue";
document.querySelectorAll('[data-vue]').forEach(el => {
new Vue({
el: el,
components: components
});
});
使用 import-glob-loader
.
确保您的 SFC 中有 <style lang="scss">
您也可以尝试删除 package-lock 和 node_modules 文件夹并进行全新安装。如果依赖项未使用兼容版本,有时这可以解决问题。
更新
要使用 glob 样式导入,您可能需要使用 import-glob
https://www.npmjs.com/package/import-glob
您也可以使用全局组件注册来实现类似的结果。这在官方文档中有很好的记录: https://vuejs.org/v2/guide/components-registration.html#Automatic-Global-Registration-of-Base-Components
仅导入 vue
文件不足以使它们可供使用。您还必须使用 Vue 注册它们。
所以,这是错误的:
import 'component.vue';
new Vue({el: '#app'});
这是对的:
import component from 'component.vue';
new Vue({
el: '#app',
components: {
'component': component
}
});
这会确保它们可用。
<style>
元素不起作用的原因是因为我没有针对 CSS
文件的 webpack 规则 - 仅针对 SCSS
文件。感谢@Daniel 指出我需要 <style lang="scss">
.
vue-style-loader
只需要将样式注入 DOM 作为 <style>
元素,我实际上并不使用这些元素(我使用 mini-css-extract-plugin
创建 css
-文件)也根据文档:
However, since this is included as a dependency and used by default in vue-loader, in most cases you don't need to configure this loader yourself.
将创建一个关于 glob 导入的单独问题。