Javascript 在Web包中使用引导的首选方法
大家好, 我一直在玩Webpack的Bootstrap,但我已经到了撕头发的地步了。我已经浏览了大量的博客文章,他们要么使用了7个月前过时的“bootstrapwebpack”插件(令人惊讶的是,这个插件并没有开箱即用),要么。。它们通过导入“node_modules/*/Bootstrap/css/Bootstrap.css”包含引导文件 当然,必须有一种更干净、更有效的方法来解决这个问题 这是我当前的Javascript 在Web包中使用引导的首选方法,javascript,twitter-bootstrap,webpack,vue.js,babeljs,Javascript,Twitter Bootstrap,Webpack,Vue.js,Babeljs,大家好, 我一直在玩Webpack的Bootstrap,但我已经到了撕头发的地步了。我已经浏览了大量的博客文章,他们要么使用了7个月前过时的“bootstrapwebpack”插件(令人惊讶的是,这个插件并没有开箱即用),要么。。它们通过导入“node_modules/*/Bootstrap/css/Bootstrap.css”包含引导文件 当然,必须有一种更干净、更有效的方法来解决这个问题 这是我当前的webpack.config.js文件: var webpack = require('we
webpack.config.js
文件:
var webpack = require('webpack');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var autoprefixer = require('autoprefixer');
var path = require('path');
module.exports = {
entry: {
app: path.resolve(__dirname, 'src/js/main.js')
},
module: {
loaders: [{
test: /\.js[x]?$/,
loaders: ['babel-loader?presets[]=es2015&presets[]=react'],
exclude: /(node_modules|bower_components)/
}, {
test: /\.css$/,
loaders: ['style', 'css']
}, {
test: /\.scss$/,
loaders: ['style', 'css', 'postcss', 'sass']
}, {
test: /\.sass$/,
loader: 'style!css!sass?sourceMap'
},{
test: /\.less$/,
loaders: ['style', 'css', 'less']
}, {
test: /\.woff$/,
loader: "url-loader?limit=10000&mimetype=application/font-woff&name=[path][name].[ext]"
}, {
test: /\.woff2$/,
loader: "url-loader?limit=10000&mimetype=application/font-woff2&name=[path][name].[ext]"
}, {
test: /\.(eot|ttf|svg|gif|png)$/,
loader: "file-loader"
}]
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '/js/bundle.js',
sourceMapFilename: '/js/bundle.map',
publicPath: '/'
},
plugins: [
new ExtractTextPlugin('style.css')
],
postcss: [
autoprefixer({
browsers: ['last 2 versions']
})
],
resolve: {
extensions: ['', '.js', '.sass'],
modulesDirectories: ['src', 'node_modules']
},
devServer: {
inline: true,
contentBase: './dist'
}
};
我可以去require('bootstrap')
(通过某种方式让jQuery工作),但是。。我很好奇你们的想法和行为
提前感谢:)我不确定这是否是最好的方法,但下面的工作对我来说是非常好的
vue.js
webapp。您可以看到工作代码
我已将引导程序所需的文件包括在以下文件中:
<head>
<meta charset="utf-8">
<title>Hey</title>
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui">
<link rel="stylesheet" href="/static/bootstrap.css" type="text/css">
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.3.7/js/tether.min.js" integrity="sha384-XTs3FgkjiBgo8qjEjBk0tGmf3wPrWtA6coPfQDfFEY8AnYJwjalXCiosYRBIBZX8" crossorigin="anonymous"></script>
<script href="/static/bootstrap.js"></script>
</head>
并确保您可以在组件中使用sass loader:
npm install sass-loader node-sass --save-dev
现在转到您的webpack配置文件并添加具有以下内容的sassLoader对象:
sassLoader: {
includePaths: [
path.resolve(projectRoot, 'node_modules/bootstrap/scss/'),
],
},
<style lang="scss">
@import "bootstrap";
</style>
projectRoot
应该只指向可以从中导航到node\u包的位置,在我的例子中是:path.resolve(\uu dirname,../)
现在,您可以在.vue文件中直接使用引导,当您添加以下内容时,webpack将为您编译引导:
sassLoader: {
includePaths: [
path.resolve(projectRoot, 'node_modules/bootstrap/scss/'),
],
},
<style lang="scss">
@import "bootstrap";
</style>
@导入“引导”;
我强烈建议使用。您可以在根文件夹中添加一个配置文件(.bootstraprc
),从中可以排除不需要的引导元素,并告知变量.scss
和引导.overrides.scss
的位置。定义SCSS变量,进行覆盖,添加webpack条目,继续生活。我使用webpack直接从.less和.SCSS文件构建引导。这允许通过覆盖.less/.scss中的源代码自定义引导,并且仍然可以获得webpack的所有好处
您的代码缺少任何.css/.less/.scss文件的入口点。您需要为已编译的css文件包含一个入口点。对于这个入口点,我用const
声明一个数组,然后在数组中包含我希望webpack编译的源文件的路径
目前,我正在使用Bootstrap3和一个基本自定义模板以及第二个自定义主题。基本模板使用bootstrap.less文件样式,并且在.less文件中写入特定的源代码重写
第二个自定义主题使用.sass文件样式,并具有类似于用.scss文件编写的引导程序基的覆盖。因此,我需要尝试优化所有这些样式以用于生产(目前约400kb,但这有点沉重,因为我们选择避免CDN,因为我们的目标是在中国使用)
下面是一个参考webpack.config.js,它可以从.less/.scss/.css文件构建,还可以做一些其他事情,比如构建typescript模块,并使用Babel将es6/typescript转换为与浏览器兼容的javascript。输出结果最终会出现在我的/static/dist
文件夹中
const path = require('path');
const webpack = require('webpack');
// plugins
const ForkTsCheckerNotifierWebpackPlugin = require('fork-ts-checker-notifier-webpack-plugin');
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
const ManifestPlugin = require('webpack-manifest-plugin');
const MomentLocalesPlugin = require('moment-locales-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const TerserJSPlugin = require('terser-webpack-plugin');
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
// take debug mode from the environment
const debug = (process.env.NODE_ENV !== 'production');
// Development asset host (webpack dev server)
const publicHost = debug ? 'http://localhost:9001' : '';
const rootAssetPath = path.join(__dirname, 'src');
const manifestOptions = {
publicPath: `${publicHost}/static/dist/`,
};
const babelLoader = {
loader: 'babel-loader',
options: {
cacheDirectory: true,
presets: [
'@babel/preset-env'
]
}
};
const app_css = [
// specific order generally matters
path.join(__dirname, 'src', 'bootstrap-template1', 'assets', 'css', 'fonts', 'Roboto', 'css', 'fonts.css'),
path.join(__dirname, 'node_modules', 'font-awesome', 'css', 'font-awesome.css'),
// This is bootstrap 3.3.7 base styling writtin in .less
path.join(__dirname, 'src', 'bootstrap-template1', 'assets', 'less', '_main_full', 'bootstrap.less'),
// bootstrap theme in .scss -> src\bp\folder\theme\src\scss\styles.scss
path.join(__dirname, 'src', 'bp', 'folder', 'theme', 'src', 'scss', 'styles.scss'),
// back to .less -> 'src/bootstrap-template1/assets/less/_main_full/core.less',
path.join(__dirname, 'src', 'bootstrap-template1', 'assets', 'less', '_main_full', 'core.less'),
// 'src/bootstrap-template1/assets/less/_main_full/components.less',
path.join(__dirname, 'src', 'bootstrap-template1', 'assets', 'less', '_main_full', 'components.less'),
//'src/bootstrap-template1/assets/less/_main_full/colors.less',
path.join(__dirname, 'src', 'bootstrap-template1', 'assets', 'less', '_main_full', 'colors.less'),
// <!-- syntax highlighting in .css --> src/bp/folder/static/css/pygments.css
path.join(__dirname, 'src', 'bp', 'folder', 'static', 'css', 'pygments.css'),
// <!-- lato/ptsans font we want to serve locally --> src/fonts/googlefonts.css'
path.join(__dirname, 'src', 'fonts', 'googlefonts.css'),
// a .css style -> 'src/bp/appbase/styles/md_table_generator.css'
path.join(__dirname, 'src', 'bp', 'appbase', 'styles', 'md_table_generator.css'),
// another .css style -> hopscotch 'src/libs/hopscotch/dist/css/hopscotch.min.css'
path.join(__dirname, 'src', 'libs', 'hopscotch', 'dist', 'css', 'hopscotch.min.css'),
//LAST final custom snippet styles to ensure they take priority 'src/css/style.css',
path.join(__dirname, 'src', 'css', 'style.css')
];
const vendor_js = [
//'core-js',
'whatwg-fetch',
];
const app_js = [
// a typescript file! :)
path.join(__dirname, 'src', 'typescript', 'libs', 'md-table', 'src', 'extension.ts'),
// base bootstrap 3.3.7 javascript
path.join(__dirname, 'node_modules', 'bootstrap', 'dist', 'js', 'bootstrap.js'),
path.join(__dirname, 'src', 'main', 'app.js'),
// src/bootstrap-template1/assets/js/plugins/forms/styling/uniform.min.js'
path.join(__dirname, 'node_modules', '@imanov', 'jquery.uniform', 'src', 'js', 'jquery.uniform.js'),
// src/bootstrap-template1/assets/js/plugins/ui/moment/moment.min.js'
];
function recursiveIssuer(m) {
if (m.issuer) {
return recursiveIssuer(m.issuer);
} else if (m.name) {
return m.name;
} else {
return false;
}
}
module.exports = {
context: process.cwd(), // to automatically find tsconfig.json
// context: __dirname,
entry: {
app_css,
vendor_js,
app_js,
},
output: {
path: path.resolve(__dirname, 'dist'),
publicPath: `${publicHost}/static/dist/`,
chunkFilename: '[id].[hash:7].js',
filename: '[name].[hash:7].js'
},
resolve: {
extensions: [".webpack.js", ".web.js",".tsx", ".ts", ".js", ".css"],
alias: {
jquery$: path.resolve(__dirname, 'node_modules', 'jquery', 'dist', 'jquery.js'),
}
},
target: "web",
devtool: 'source-map',
devServer: {
// this devserver proxies all requests to my python development server except
// webpack compiled files in the `/static/dist` folder
clientLogLevel: 'warning',
contentBase: path.join(__dirname, './src'),
publicPath: 'dist',
open: true,
historyApiFallback: true,
stats: 'errors-only',
headers: {'Access-Control-Allow-Origin': '*'},
watchContentBase: true,
port: 9001,
proxy: {
'!(/dist/**/**.*)': {
target: 'http://127.0.0.1:8000',
},
},
},
mode: process.env.NODE_ENV === 'production' ? 'production' : 'development',
optimization: {
minimizer: [new TerserJSPlugin({}), new OptimizeCssAssetsPlugin({})],
splitChunks: {
cacheGroups: {
appStyles: {
name: 'app',
// https://webpack.js.org/plugins/mini-css-extract-plugin/#extracting-css-based-on-entry
test: (m, c, entry = 'app') =>
m.constructor.name === 'CssModule' && recursiveIssuer(m) === entry,
chunks: 'all',
enforce: true,
},
},
},
},
plugins: [
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
'window.jQuery': 'jquery',
'window.$': 'jquery'
}),
// Strip all locales from moment.js except "zh-cn"
// ("en" is built into Moment and can’t be removed)
new MomentLocalesPlugin({
localesToKeep: ['zh-cn'],
}),
new ForkTsCheckerWebpackPlugin({
tslint: true, useTypescriptIncrementalApi: true
}),
new ForkTsCheckerNotifierWebpackPlugin({ title: 'TypeScript', excludeWarnings: false }),
new MiniCssExtractPlugin({
filename: '[name].[hash:7].css',
chunkFilename: '[id].[hash:7].css',
moduleFilename: ({ name }) => `${name.replace('/js/', '/css/')}.[hash:7].css`
}),
new OptimizeCssAssetsPlugin({
assetNameRegExp: /\.optimize\.css$/g,
cssProcessor: require('cssnano'),
cssProcessorPluginOptions: {
preset: ['default', { discardComments: { removeAll: true } }],
},
canPrint: true
}),
new ManifestPlugin({
...manifestOptions
}),
].concat(debug ? [] : [
// production webpack plugins go here
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify('production'),
}
}),
new ForkTsCheckerWebpackPlugin({
async: false,
useTypescriptIncrementalApi: true,
memoryLimit: 2048
}),
]),
module: {
rules: [
{
// jinja/nunjucks templates
test: /\.jinja2$/,
loader: 'jinja-loader',
query: {
root:'../templates'
}
},
{
test: /\.ts(x?)$/,
exclude: /node_modules/,
use: [
babelLoader,
{
loader: 'ts-loader',
options:
{ // disable type checker - we will use it in
// fork-ts-checker-webpack-plugin
transpileOnly: true
}
}
]
},
{
test: /\.js$/,
exclude: /node_modules/,
use: [
babelLoader
]
},
{
test: /\.(html|jinja2)$/,
loader: 'raw-loader'
},
{
test: /\.(sc|sa|c)ss$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
hmr: debug,
// only use if hmr is not working correctly
// reloadAll: true,
},
},
{
loader: "css-loader",
},
{
loader: "sass-loader"
},
]
},
{
test: /\.less$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
hmr: debug,
// only use if hmr is not working correctly
// reloadAll: true,
},
},
{
loader: 'css-loader', // translates CSS into CommonJS
},
{
loader: 'less-loader', // compiles Less to CSS
},
],
},
{
test: /\.(ttf|eot|svg|gif|ico)$/,
use: [
{
loader: 'file-loader',
options: {
name: '[path][name].[hash:7].[ext]',
context: rootAssetPath
},
},
],
},
{
test: /\.(jpe?g|png)$/i,
loader: 'responsive-loader',
options: {
name: '[path][name].[hash:7].[ext]',
adapter: require('responsive-loader/sharp'),
context: rootAssetPath
}
},
{
test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
loader:'url-loader',
options:{
limit: 10000,
mimetype: 'application/font-woff',
// name: ('fonts/[path][name].[hash:7].[ext]'),
name: ('fonts/[name].[hash:7].[ext]'),
}
},
{
test: require.resolve("jquery"),
use:[
{ loader: "expose-loader", options:"$" },
{ loader: "expose-loader", options:"jQuery" },
{ loader: "expose-loader", options:"jquery" }
]
}
]
},
};
const path=require('path');
const webpack=require('webpack');
//插件
const forktscheckenotifierwebpackplugin=require('fork-ts-checker-notifier-webpack-plugin');
const ForkTsCheckerWebpackPlugin=require('fork-ts-checker-webpack-plugin');
const ManifestPlugin=require('webpack-manifest-plugin');
const MomentLocalesPlugin=require('moment-locales-webpack-plugin');
const MiniCssExtractPlugin=require('mini-css-extract-plugin');
const TerserJSPlugin=require('terser-webpack-plugin');
const optimizecssassetplugin=require('optimize-css-assets-webpack-plugin');
//从环境中获取调试模式
const debug=(process.env.NODE_env!='production');
//开发资产主机(Web包开发服务器)
const publicHost=debug?'http://localhost:9001' : '';
const rootAssetPath=path.join(uu dirname,'src');
常量选项={
publicPath:`${publicHost}/static/dist/`,
};
康斯特巴贝洛德={
加载器:“巴别塔加载器”,
选项:{
cacheDirectory:true,
预设:[
“@babel/preset env”
]
}
};
const app_css=[
//具体的顺序通常很重要
join(uuu dirname,'src','bootstrap-template1','assets','css','font','Roboto','css','fonts.css'),
join(uuu dirname,'node_modules','font awesome','css','font awesome.css'),
//这是bootstrap 3.3.7基本样式写入。更少
join(u dirname,'src','bootstrap-template1','assets','less','u main_full','bootstrap.less'),
//.scss->src\bp\folder\theme\src\scss\styles.scss中的引导主题
join(uuu dirname,'src','bp','folder','theme','src','scss','styles.scss'),
//回到.less->“src/bootstrap-template1/assets/less/\u main\u full/core.less”,
join(uu dirname,'src','bootstrap-template1','assets','less','umain_ufull','core.less'),
//“src/bootstrap-template1/assets/less/\u main\u full/components.less”,
join(uu dirname,'src','bootstrap-template1','assets','less','umain_ufull','components.less'),
//“src/bootstrap-template1/assets/less/\u main\u full/colors.less”,
join(uu dirname,'src','bootstrap-template1','assets','less','umain_ufull','colors.less'),
//src/bp/folder/static/css/pygments.css
join(uuu dirname,'src','bp','folder','static','css','pygments.css'),
//src/fonts/googlefonts.css'
join(uu dirname,'src','font','googlefonts.css'),
//css style->'src/bp/appbase/styles/md_table_generator.css'
join(uuu dirname,'src','bp','appbase','styles','md\u table\u generator.css'),
//另一个.css样式->hopscotch'src/libs/hopscotch/dist/css/hopscotch.min.css'
join(uu dirname,'src','libs','hopsocch','dist','css','hopsocch.min.css'),
//最后一个自定义代码段样式,以确保它们优先于“src/css/style.css”,
path.join(_dirname,